summaryrefslogtreecommitdiffstats
path: root/bsps/arm/altera-cyclone-v/contrib/hwlib/src/hwmgr/alt_clock_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/altera-cyclone-v/contrib/hwlib/src/hwmgr/alt_clock_manager.c')
-rw-r--r--bsps/arm/altera-cyclone-v/contrib/hwlib/src/hwmgr/alt_clock_manager.c5554
1 files changed, 5554 insertions, 0 deletions
diff --git a/bsps/arm/altera-cyclone-v/contrib/hwlib/src/hwmgr/alt_clock_manager.c b/bsps/arm/altera-cyclone-v/contrib/hwlib/src/hwmgr/alt_clock_manager.c
new file mode 100644
index 0000000000..95404c1c13
--- /dev/null
+++ b/bsps/arm/altera-cyclone-v/contrib/hwlib/src/hwmgr/alt_clock_manager.c
@@ -0,0 +1,5554 @@
+/******************************************************************************
+ *
+ * Copyright 2013 Altera Corporation. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ ******************************************************************************/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <bsp/socal/hps.h>
+#include <bsp/socal/socal.h>
+#include <bsp/socal/alt_sysmgr.h>
+#include <bsp/hwlib.h>
+#include <bsp/alt_clock_manager.h>
+#include <bsp/alt_mpu_registers.h>
+
+#define UINT12_MAX (4096)
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Useful Structures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ /* General structure used to hold parameters of various clock entities, */
+typedef struct ALT_CLK_PARAMS_s
+{
+ alt_freq_t freqcur; // current frequency of the clock
+ alt_freq_t freqmin; // minimum allowed frequency for this clock
+ alt_freq_t freqmax; // maximum allowed frequency for this clock
+ uint32_t guardband : 7; // guardband percentage (0-100) if this clock
+ // is a PLL, ignored otherwise
+ uint32_t active : 1; // current state of activity of this clock
+} ALT_CLK_PARAMS_t;
+
+
+typedef struct ALT_EXT_CLK_PARAMBLOK_s
+{
+ ALT_CLK_PARAMS_t clkosc1; // ALT_CLK_OSC1
+ ALT_CLK_PARAMS_t clkosc2; // ALT_CLK_OSC2
+ ALT_CLK_PARAMS_t periph; // ALT_CLK_F2H_PERIPH_REF
+ ALT_CLK_PARAMS_t sdram; // ALT_CLK_F2H_SDRAM_REF
+} ALT_EXT_CLK_PARAMBLOK_t;
+
+
+ /* Initializes the External Clock Frequency Limits block */
+ /* The first field is the current external clock frequency, and can be set by */
+ /* alt_clk_ext_clk_freq_set(), the second and third fields are the minimum and */
+ /* maximum frequencies, the fourth field is ignored, and the fifth field */
+ /* contains the current activity state of the clock, 1=active, 0=inactive. */
+ /* Values taken from Section 2.3 and Section 2.7.1 of the HHP HPS-Clocking */
+ /* NPP specification. */
+static ALT_EXT_CLK_PARAMBLOK_t alt_ext_clk_paramblok =
+{
+ { 25000000, 10000000, 50000000, 0, 1 },
+ { 25000000, 10000000, 50000000, 0, 1 },
+ { 0, 10000000, 50000000, 0, 1 },
+ { 0, 10000000, 50000000, 0, 1 }
+};
+
+
+ /* PLL frequency limits */
+typedef struct ALT_PLL_CLK_PARAMBLOK_s
+{
+ ALT_CLK_PARAMS_t MainPLL_600; // Main PLL values for 600 MHz SoC
+ ALT_CLK_PARAMS_t PeriphPLL_600; // Peripheral PLL values for 600 MHz SoC
+ ALT_CLK_PARAMS_t SDRAMPLL_600; // SDRAM PLL values for 600 MHz SoC
+ ALT_CLK_PARAMS_t MainPLL_800; // Main PLL values for 800 MHz SoC
+ ALT_CLK_PARAMS_t PeriphPLL_800; // Peripheral PLL values for 800 MHz SoC
+ ALT_CLK_PARAMS_t SDRAMPLL_800; // SDRAM PLL values for 800 MHz SoC
+} ALT_PLL_CLK_PARAMBLOK_t;
+
+
+ /* Initializes the PLL frequency limits block */
+ /* The first field is the current frequency, the second and third fields */
+ /* are the design limits of the PLLs as listed in Section 3.2.1.2 of the */
+ /* HHP HPS-Clocking NPP document. The fourth field of each line is the */
+ /* guardband percentage, and the fifth field of each line is the current */
+ /* state of the PLL, 1=active, 0=inactive. */
+#define ALT_ORIGINAL_GUARDBAND_VAL 20
+#define ALT_GUARDBAND_LIMIT 20
+
+static ALT_PLL_CLK_PARAMBLOK_t alt_pll_clk_paramblok =
+{
+ { 0, 320000000, 1200000000, ALT_ORIGINAL_GUARDBAND_VAL, 0 },
+ { 0, 320000000, 900000000, ALT_ORIGINAL_GUARDBAND_VAL, 0 },
+ { 0, 320000000, 800000000, ALT_ORIGINAL_GUARDBAND_VAL, 0 },
+ { 0, 320000000, 1600000000, ALT_ORIGINAL_GUARDBAND_VAL, 1 },
+ { 0, 320000000, 1250000000, ALT_ORIGINAL_GUARDBAND_VAL, 1 },
+ { 0, 320000000, 1066000000, ALT_ORIGINAL_GUARDBAND_VAL, 1 }
+};
+
+
+ /* PLL counter frequency limits */
+typedef struct ALT_PLL_CNTR_FREQMAX_s
+{
+ alt_freq_t MainPLL_C0; // Main PLL Counter 0 parameter block
+ alt_freq_t MainPLL_C1; // Main PLL Counter 1 parameter block
+ alt_freq_t MainPLL_C2; // Main PLL Counter 2 parameter block
+ alt_freq_t MainPLL_C3; // Main PLL Counter 3 parameter block
+ alt_freq_t MainPLL_C4; // Main PLL Counter 4 parameter block
+ alt_freq_t MainPLL_C5; // Main PLL Counter 5 parameter block
+ alt_freq_t PeriphPLL_C0; // Peripheral PLL Counter 0 parameter block
+ alt_freq_t PeriphPLL_C1; // Peripheral PLL Counter 1 parameter block
+ alt_freq_t PeriphPLL_C2; // Peripheral PLL Counter 2 parameter block
+ alt_freq_t PeriphPLL_C3; // Peripheral PLL Counter 3 parameter block
+ alt_freq_t PeriphPLL_C4; // Peripheral PLL Counter 4 parameter block
+ alt_freq_t PeriphPLL_C5; // Peripheral PLL Counter 5 parameter block
+ alt_freq_t SDRAMPLL_C0; // SDRAM PLL Counter 0 parameter block
+ alt_freq_t SDRAMPLL_C1; // SDRAM PLL Counter 1 parameter block
+ alt_freq_t SDRAMPLL_C2; // SDRAM PLL Counter 2 parameter block
+ alt_freq_t SDRAMPLL_C5; // SDRAM PLL Counter 5 parameter block
+} ALT_PLL_CNTR_FREQMAX_t;
+
+//
+// The following pll max frequency array statically defined must be recalculated each time
+// when powering up, by calling alt_clk_clkmgr_init()
+//
+// for 14.1 uboot preloader, the following values are calculated dynamically.
+//
+// Arrial 5
+// alt_pll_cntr_maxfreq.MainPLL_C0 = 1050000000
+// alt_pll_cntr_maxfreq.MainPLL_C1 = 350000000
+// alt_pll_cntr_maxfreq.MainPLL_C2 = 262500000
+// alt_pll_cntr_maxfreq.MainPLL_C3 = 350000000
+// alt_pll_cntr_maxfreq.MainPLL_C4 = 2050781
+// alt_pll_cntr_maxfreq.MainPLL_C5 = 116666666
+// alt_pll_cntr_maxfreq.PeriphPLL_C0 = 1953125
+// alt_pll_cntr_maxfreq.PeriphPLL_C1 = 250000000
+// alt_pll_cntr_maxfreq.PeriphPLL_C2 = 1953125
+// alt_pll_cntr_maxfreq.PeriphPLL_C3 = 200000000
+// alt_pll_cntr_maxfreq.PeriphPLL_C4 = 200000000
+// alt_pll_cntr_maxfreq.PeriphPLL_C5 = 1953125
+// alt_pll_cntr_maxfreq.SDRAMPLL_C0 = 533333333
+// alt_pll_cntr_maxfreq.SDRAMPLL_C1 = 1066666666
+// alt_pll_cntr_maxfreq.SDRAMPLL_C2 = 533333333
+// alt_pll_cntr_maxfreq.SDRAMPLL_C5 = 177777777
+
+// Cyclone V
+// alt_pll_cntr_maxfreq.MainPLL_C0 = 925000000
+// alt_pll_cntr_maxfreq.MainPLL_C1 = 370000000
+// alt_pll_cntr_maxfreq.MainPLL_C2 = 462500000
+// alt_pll_cntr_maxfreq.MainPLL_C3 = 370000000
+// alt_pll_cntr_maxfreq.MainPLL_C4 = 3613281
+// alt_pll_cntr_maxfreq.MainPLL_C5 = 123333333
+// alt_pll_cntr_maxfreq.PeriphPLL_C0 = 1953125
+// alt_pll_cntr_maxfreq.PeriphPLL_C1 = 250000000
+// alt_pll_cntr_maxfreq.PeriphPLL_C2 = 1953125
+// alt_pll_cntr_maxfreq.PeriphPLL_C3 = 200000000
+// alt_pll_cntr_maxfreq.PeriphPLL_C4 = 200000000
+// alt_pll_cntr_maxfreq.PeriphPLL_C5 = 1953125
+// alt_pll_cntr_maxfreq.SDRAMPLL_C0 = 400000000
+// alt_pll_cntr_maxfreq.SDRAMPLL_C1 = 800000000
+// alt_pll_cntr_maxfreq.SDRAMPLL_C2 = 400000000
+// alt_pll_cntr_maxfreq.SDRAMPLL_C5 = 133333333
+
+
+/* Initializes the PLL Counter output maximum frequency block */
+static ALT_PLL_CNTR_FREQMAX_t alt_pll_cntr_maxfreq =
+{
+ 800000000, /* Main PLL Outputs */
+ 400000000,
+ 400000000,
+ 432000000,
+ 250000000,
+ 125000000,
+ 250000000, /* Peripheral PLL Outputs */
+ 250000000,
+ 432000000,
+ 250000000,
+ 200000000,
+ 100000000, /* SDRAM PLL Outputs */
+ 533000000,
+ 1066000000,
+ 533000000,
+ 200000000
+};
+
+
+
+ /* Maximum multiply, divide, and counter divisor values for each PLL */
+#define ALT_CLK_PLL_MULT_MAX 4095
+#define ALT_CLK_PLL_DIV_MAX 63
+#define ALT_CLK_PLL_CNTR_MAX 511
+
+
+ /* Definitions for the reset request and reset acknowledge bits */
+ /* for each of the output counters for each of the PLLS */
+#define ALT_CLK_PLL_RST_BIT_C0 0x00000001
+#define ALT_CLK_PLL_RST_BIT_C1 0x00000002
+#define ALT_CLK_PLL_RST_BIT_C2 0x00000004
+#define ALT_CLK_PLL_RST_BIT_C3 0x00000008
+#define ALT_CLK_PLL_RST_BIT_C4 0x00000010
+#define ALT_CLK_PLL_RST_BIT_C5 0x00000020
+
+
+ /* These are the bits that deal with PLL lock and this macro */
+ /* defines a mask to test for bits outside of these */
+#define ALT_CLK_MGR_PLL_LOCK_BITS (ALT_CLKMGR_INTREN_MAINPLLACHIEVED_CLR_MSK \
+ & ALT_CLKMGR_INTREN_PERPLLACHIEVED_CLR_MSK \
+ & ALT_CLKMGR_INTREN_SDRPLLACHIEVED_CLR_MSK \
+ & ALT_CLKMGR_INTREN_MAINPLLLOST_CLR_MSK \
+ & ALT_CLKMGR_INTREN_PERPLLLOST_CLR_MSK \
+ & ALT_CLKMGR_INTREN_SDRPLLLOST_CLR_MSK)
+
+
+// Undocumented register which determines clock dividers for main PLL C0, C1, and C2. These should be considered RO.
+#define ALT_CLKMGR_ALTERA_OFST 0xe0
+#define ALT_CLKMGR_ALTERA_MPUCLK_OFST 0x0
+#define ALT_CLKMGR_ALTERA_MAINCLK_OFST 0x4
+#define ALT_CLKMGR_ALTERA_DBGATCLK_OFST 0x8
+#define ALT_CLKMGR_ALTERA_ADDR ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ADDR) + ALT_CLKMGR_ALTERA_OFST))
+#define ALT_CLKMGR_ALTERA_MPUCLK_ADDR ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ALTERA_ADDR) + ALT_CLKMGR_ALTERA_MPUCLK_OFST))
+#define ALT_CLKMGR_ALTERA_MAINCLK_ADDR ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ALTERA_ADDR) + ALT_CLKMGR_ALTERA_MAINCLK_OFST))
+#define ALT_CLKMGR_ALTERA_DBGATCLK_ADDR ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ALTERA_ADDR) + ALT_CLKMGR_ALTERA_DBGATCLK_OFST))
+#define ALT_CLKMGR_ALTERA_MPUCLK_CNT_GET(value) (((value) & 0x000001ff) >> 0)
+#define ALT_CLKMGR_ALTERA_MAINCLK_CNT_GET(value) (((value) & 0x000001ff) >> 0)
+#define ALT_CLKMGR_ALTERA_DBGATCLK_CNT_GET(value) (((value) & 0x000001ff) >> 0)
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Utility functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+/****************************************************************************************/
+/* alt_clk_mgr_wait() introduces a delay, not very exact, but very light in */
+/* implementation. Depending upon the optinization level, it will wait at least the */
+/* number of clock cycles specified in the cnt parameter, sometimes many more. The */
+/* reg parameter is set to a register or a memory location that was recently used (so */
+/* as to avoid accidently evicting a register and a recently-used cache line in favor */
+/* of one whose values are not actually needed.). The cnt parameter sets the number of */
+/* repeated volatile memory reads and so sets a minimum time delay measured in */
+/* mpu_clk cycles. If mpu_clk = osc1 clock (as in bypass mode), then this gives a */
+/* minimum osc1 clock cycle delay. */
+/****************************************************************************************/
+
+inline static void alt_clk_mgr_wait(void* reg, uint32_t cnt)
+{
+ for (; cnt ; cnt--)
+ {
+ (void) alt_read_word(reg);
+ }
+}
+
+ /* Wait time constants */
+ /* These values came from Section 4.9.4 of the HHP HPS-Clocking NPP document */
+#define ALT_SW_MANAGED_CLK_WAIT_CTRDIV 30 /* 30 or more MPU clock cycles */
+#define ALT_SW_MANAGED_CLK_WAIT_HWCTRDIV 40
+#define ALT_SW_MANAGED_CLK_WAIT_BYPASS 30
+#define ALT_SW_MANAGED_CLK_WAIT_SAFEREQ 30
+#define ALT_SW_MANAGED_CLK_WAIT_SAFEEXIT 30
+#define ALT_SW_MANAGED_CLK_WAIT_NANDCLK 8 /* 8 or more MPU clock cycles */
+
+
+#define ALT_BYPASS_TIMEOUT_CNT 50
+ // arbitrary number until i find more info
+#define ALT_TIMEOUT_PHASE_SYNC 300
+ // how many loops to wait for the SDRAM clock to come around
+ // to zero and allow for writing a new divisor ratio to it
+
+ALT_STATUS_CODE alt_clk_plls_settle_wait(void)
+{
+ int32_t i = ALT_BYPASS_TIMEOUT_CNT;
+ bool nofini;
+
+ do
+ {
+ nofini = alt_read_word(ALT_CLKMGR_STAT_ADDR) & ALT_CLKMGR_STAT_BUSY_SET_MSK;
+ } while (nofini && i--);
+ // wait until clocks finish transitioning and become stable again
+ return (i > 0) ? ALT_E_SUCCESS : ALT_E_ERROR;
+}
+
+static ALT_STATUS_CODE alt_clk_pll_lock_wait(ALT_CLK_t pll, uint32_t timeout)
+{
+ uint32_t locked_mask = 0;
+
+ if (pll == ALT_CLK_MAIN_PLL) { locked_mask = ALT_CLKMGR_INTER_MAINPLLLOCKED_SET_MSK; }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL) { locked_mask = ALT_CLKMGR_INTER_PERPLLLOCKED_SET_MSK; }
+ else if (pll == ALT_CLK_SDRAM_PLL) { locked_mask = ALT_CLKMGR_INTER_SDRPLLLOCKED_SET_MSK; }
+ else
+ {
+ return ALT_E_BAD_ARG;
+ }
+
+ do
+ {
+ uint32_t int_status = alt_read_word(ALT_CLKMGR_INTER_ADDR);
+ if (int_status & locked_mask)
+ {
+ return ALT_E_SUCCESS;
+ }
+
+ } while (timeout--);
+
+ return ALT_E_TMO;
+}
+
+ /* Useful utility macro for checking if two values */
+ /* are within a certain percentage of each other */
+#define alt_within_delta(ref, neu, prcnt) (((((neu) * 100)/(ref)) < (100 + (prcnt))) \
+ && ((((neu) * 100)/(ref)) > (100 - (prcnt))))
+
+
+ /* Flags to include or omit code sections */
+// There are four cases where there is a small possibility of producing clock
+// glitches. Code has been added from an abundance of caution to prevent
+// these glitches. If further testing shows that this extra code is not necessary
+// under any conditions, it may be easily eliminated by clearing these flags.
+
+#define ALT_PREVENT_GLITCH_BYP true
+// for PLL entering or leaving bypass
+#define ALT_PREVENT_GLITCH_EXSAFE true
+// for PLL exiting safe mode
+#define ALT_PREVENT_GLITCH_CNTRRST true
+// resets counter phase
+#define ALT_PREVENT_GLITCH_CHGC1 true
+// for changing Main PLL C1 counter
+
+
+
+/****************************************************************************************/
+/* Bare-bones utility function used to make the somewhat complex writes to the PLL */
+/* counter registers (the clock dividers) easier. No parameter-checking or */
+/* error-checking, this is a static to this file and invisible to Doxygen. */
+/****************************************************************************************/
+
+static void alt_clk_pllcounter_write(void* vcoaddr, void* stataddr, void* cntraddr,
+ uint32_t val, uint32_t msk, uint32_t shift)
+{
+#if ALT_PREVENT_GLITCH_CNTRRST
+ // this is here from an abundance of caution and it may not be necessary
+ // to put the counter in reset for this write
+ volatile uint32_t temp;
+
+ alt_setbits_word(vcoaddr, msk << shift); // put the counter in reset
+ do
+ {
+ temp = alt_read_word(stataddr);
+ } while (!(temp & msk));
+
+ alt_write_word(cntraddr, val);
+ alt_clrbits_word(vcoaddr, msk << shift); // release counter reset
+
+#else // should we find out that resetting the counters as above is unnecessary
+ alt_write_word(cntraddr, val);
+#endif
+}
+
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Main Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+/****************************************************************************************/
+/* alt_clk_lock_status_clear() clears assertions of one or more of the PLL lock status */
+/* conditions. */
+/****************************************************************************************/
+
+ALT_STATUS_CODE alt_clk_lock_status_clear(ALT_CLK_PLL_LOCK_STATUS_t lock_stat_mask)
+{
+ if (lock_stat_mask & ( ALT_CLKMGR_INTER_MAINPLLACHIEVED_CLR_MSK
+ & ALT_CLKMGR_INTER_PERPLLACHIEVED_CLR_MSK
+ & ALT_CLKMGR_INTER_SDRPLLACHIEVED_CLR_MSK
+ & ALT_CLKMGR_INTER_MAINPLLLOST_CLR_MSK
+ & ALT_CLKMGR_INTER_PERPLLLOST_CLR_MSK
+ & ALT_CLKMGR_INTER_SDRPLLLOST_CLR_MSK)
+ )
+ {
+ return ALT_E_BAD_ARG;
+ }
+ else
+ {
+ alt_setbits_word(ALT_CLKMGR_INTER_ADDR, lock_stat_mask);
+ return ALT_E_SUCCESS;
+ }
+}
+
+
+/****************************************************************************************/
+/* alt_clk_lock_status_get() returns the value of the PLL lock status conditions. */
+/****************************************************************************************/
+
+uint32_t alt_clk_lock_status_get(void)
+{
+ return alt_read_word(ALT_CLKMGR_INTER_ADDR) & ( ALT_CLKMGR_INTER_MAINPLLACHIEVED_SET_MSK
+ | ALT_CLKMGR_INTER_PERPLLACHIEVED_SET_MSK
+ | ALT_CLKMGR_INTER_SDRPLLACHIEVED_SET_MSK
+ | ALT_CLKMGR_INTER_MAINPLLLOST_SET_MSK
+ | ALT_CLKMGR_INTER_PERPLLLOST_SET_MSK
+ | ALT_CLKMGR_INTER_SDRPLLLOST_SET_MSK
+ | ALT_CLKMGR_INTER_MAINPLLLOCKED_SET_MSK
+ | ALT_CLKMGR_INTER_PERPLLLOCKED_SET_MSK
+ | ALT_CLKMGR_INTER_SDRPLLLOCKED_SET_MSK );
+}
+
+
+/****************************************************************************************/
+/* alt_clk_pll_is_locked() returns ALT_E_TRUE if the designated PLL is currently */
+/* locked and ALT_E_FALSE if not. */
+/****************************************************************************************/
+
+ALT_STATUS_CODE alt_clk_pll_is_locked(ALT_CLK_t pll)
+{
+ ALT_STATUS_CODE status = ALT_E_BAD_ARG;
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ status = (alt_read_word(ALT_CLKMGR_INTER_ADDR) & ALT_CLKMGR_INTER_MAINPLLLOCKED_SET_MSK)
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ status = (alt_read_word(ALT_CLKMGR_INTER_ADDR) & ALT_CLKMGR_INTER_PERPLLLOCKED_SET_MSK)
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ status = (alt_read_word(ALT_CLKMGR_INTER_ADDR) & ALT_CLKMGR_INTER_SDRPLLLOCKED_SET_MSK)
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ }
+ return status;
+}
+
+
+/****************************************************************************************/
+/* alt_clk_safe_mode_clear() clears the safe mode status of the Clock Manager following */
+/* a reset. */
+/****************************************************************************************/
+
+ALT_STATUS_CODE alt_clk_safe_mode_clear(void)
+{
+ ALT_STATUS_CODE status = ALT_E_ERROR;
+#if ALT_PREVENT_GLITCH_EXSAFE
+ uint32_t temp;
+
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp &
+ (ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK));
+ // gate off l4MP and L4SP clocks (no matter their source)
+
+ alt_setbits_word(ALT_CLKMGR_CTL_ADDR, ALT_CLKMGR_CTL_SAFEMOD_SET_MSK);
+ // clear safe mode bit
+ status = alt_clk_plls_settle_wait();
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR,
+ ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK | ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK,
+ temp);
+ // gate l4MP and L4SP clocks back on if they were on previously
+
+#else
+ alt_setbits_word(ALT_CLKMGR_CTL_ADDR, ALT_CLKMGR_CTL_SAFEMOD_SET_MSK);
+ // clear safe mode bit
+ status = alt_clk_plls_settle_wait();
+
+#endif
+ return status;
+}
+
+
+/****************************************************************************************/
+/* alt_clk_is_in_safe_mode() returns whether the specified safe mode clock domain is in */
+/* safe mode or not. */
+/****************************************************************************************/
+
+bool alt_clk_is_in_safe_mode(ALT_CLK_SAFE_DOMAIN_t clk_domain)
+{
+ bool ret = false;
+ uint32_t temp;
+
+ if (clk_domain == ALT_CLK_DOMAIN_NORMAL)
+ {
+ ret = alt_read_word(ALT_CLKMGR_CTL_ADDR) & ALT_CLKMGR_CTL_SAFEMOD_SET_MSK;
+ // is the main clock domain in safe mode?
+ }
+ else if (clk_domain == ALT_CLK_DOMAIN_DEBUG)
+ {
+ temp = alt_read_word(ALT_CLKMGR_DBCTL_ADDR);
+ if (temp & ALT_CLKMGR_DBCTL_STAYOSC1_SET_MSK)
+ {
+ ret = true; // is the debug clock domain in safe mode?
+ }
+ else if (temp & ALT_CLKMGR_DBCTL_ENSFMDWR_SET_MSK)
+ {
+ ret = alt_read_word(ALT_CLKMGR_CTL_ADDR) & ALT_CLKMGR_CTL_SAFEMOD_SET_MSK;
+ // is the debug clock domain following the main clock domain
+ // AND is the main clock domain in safe mode?
+ }
+ }
+ return ret;
+}
+
+/****************************************************************************************/
+/* alt_clk_pll_bypass_disable() disables bypass mode for the specified PLL, removing */
+/* it from bypass mode and allowing it to provide the output of the PLL to drive the */
+/* six main clocks. */
+/****************************************************************************************/
+
+ALT_STATUS_CODE alt_clk_pll_bypass_disable(ALT_CLK_t pll)
+{
+ ALT_STATUS_CODE status = ALT_E_BAD_ARG;
+ uint32_t temp;
+#if ALT_PREVENT_GLITCH_BYP
+ uint32_t temp1;
+ bool restore_0 = false;
+ bool restore_1 = false;
+#endif
+
+ // this function should only be called after the selected PLL is locked
+ if (alt_clk_pll_is_locked(pll) == ALT_E_TRUE)
+ {
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+#if ALT_PREVENT_GLITCH_BYP
+ // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
+ // bypass state, then gate clock back on. FogBugz #63778
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
+ temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK)))
+ {
+ restore_0 = true;
+ }
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK)))
+ {
+ restore_1 = true;
+ }
+ temp = temp1;
+ if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
+ if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
+#endif
+
+ // assert outresetall of main PLL
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
+ alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, temp | ALT_CLKMGR_MAINPLL_VCO_OUTRSTALL_SET_MSK);
+
+ // deassert outresetall of main PLL
+ alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, temp & ALT_CLKMGR_MAINPLL_VCO_OUTRSTALL_CLR_MSK);
+
+ alt_clk_plls_settle_wait();
+
+ // remove bypass
+ alt_clrbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_MAINPLL_SET_MSK);
+ status = alt_clk_plls_settle_wait();
+
+#if ALT_PREVENT_GLITCH_BYP
+ if (restore_0 || restore_1)
+ {
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ // wait a bit more before reenabling the L4MP and L4SP clocks
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1);
+ }
+#endif
+ }
+
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+#if ALT_PREVENT_GLITCH_BYP
+ // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
+ // bypass state, then gate clock back on. FogBugz #63778
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
+ temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK))
+ {
+ restore_0 = true;
+ }
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK))
+ {
+ restore_1 = true;
+ }
+ temp = temp1;
+ if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
+ if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
+#endif
+
+ // assert outresetall of Peripheral PLL
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+ alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp | ALT_CLKMGR_PERPLL_VCO_OUTRSTALL_SET_MSK);
+ alt_clk_plls_settle_wait();
+
+ // deassert outresetall of main PLL
+ alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp & ALT_CLKMGR_PERPLL_VCO_OUTRSTALL_CLR_MSK);
+
+ // remove bypass - don't think that there's any need to touch the bypass clock source
+ alt_clrbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_PERPLL_SET_MSK);
+ status = alt_clk_plls_settle_wait();
+
+#if ALT_PREVENT_GLITCH_BYP
+ if (restore_0 || restore_1)
+ {
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ // wait a bit more before reenabling the L4MP and L4SP clocks
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1);
+ }
+#endif
+ }
+
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ // assert outresetall of SDRAM PLL
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
+ alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp | ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_SET_MSK);
+
+ // deassert outresetall of main PLL
+ alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp & ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_CLR_MSK);
+ alt_clk_plls_settle_wait();
+
+ // remove bypass - don't think that there's any need to touch the bypass clock source
+ alt_clrbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_SDRPLLSRC_SET_MSK);
+ status = alt_clk_plls_settle_wait();
+ }
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+
+ return status;
+}
+
+
+/****************************************************************************************/
+/* alt_clk_pll_bypass_enable() enable bypass mode for the specified PLL. */
+/****************************************************************************************/
+
+ALT_STATUS_CODE alt_clk_pll_bypass_enable(ALT_CLK_t pll, bool use_input_mux)
+{
+ ALT_STATUS_CODE status = ALT_E_BAD_ARG;
+ uint32_t temp;
+#ifdef ALT_PREVENT_GLITCH_BYP
+ uint32_t temp1;
+ bool restore_0 = false;
+ bool restore_1 = false;
+#endif
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ if (!use_input_mux)
+ {
+#ifdef ALT_PREVENT_GLITCH_BYP
+ // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
+ // bypass state, then gate clock back on. FogBugz #63778
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
+ temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK)))
+ {
+ restore_0 = true;
+ }
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK)))
+ {
+ restore_1 = true;
+ }
+ temp = temp1;
+ if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
+ if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
+
+ alt_setbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_MAINPLL_SET_MSK);
+ // no input mux select on main PLL
+
+ status = alt_clk_plls_settle_wait();
+ // wait before reenabling the L4MP and L4SP clocks
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1); }
+
+#else
+ alt_setbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_MAINPLL_SET_MSK);
+ // no input mux select on main PLL
+ status = alt_clk_plls_settle_wait();
+
+#endif
+ status = ALT_E_SUCCESS;
+ }
+ else
+ {
+ status = ALT_E_BAD_ARG;
+ }
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+#ifdef ALT_PREVENT_GLITCH_BYP
+ // if L4MP or L4SP source is set to Peripheral PLL C1, gate it off before changing
+ // bypass state, then gate clock back on. FogBugz #63778
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
+ temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK))
+ {
+ restore_0 = true;
+ }
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK))
+ {
+ restore_1 = true;
+ }
+ temp = temp1;
+ if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
+ if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
+
+ temp = alt_read_word(ALT_CLKMGR_BYPASS_ADDR) &
+ (ALT_CLKMGR_BYPASS_PERPLL_CLR_MSK & ALT_CLKMGR_BYPASS_PERPLLSRC_CLR_MSK);
+ temp |= (use_input_mux) ? ALT_CLKMGR_BYPASS_PERPLL_SET_MSK |
+ ALT_CLKMGR_BYPASS_PERPLLSRC_SET_MSK : ALT_CLKMGR_BYPASS_PERPLL_SET_MSK;
+ // set bypass bit and optionally the source select bit
+
+ alt_write_word(ALT_CLKMGR_BYPASS_ADDR, temp);
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ // wait a bit before reenabling the L4MP and L4SP clocks
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1); }
+
+#else
+ temp = alt_read_word(ALT_CLKMGR_BYPASS_ADDR) &
+ (ALT_CLKMGR_BYPASS_PERPLL_CLR_MSK & ALT_CLKMGR_BYPASS_PERPLLSRC_CLR_MSK);
+ temp |= (use_input_mux) ? ALT_CLKMGR_BYPASS_PERPLL_SET_MSK |
+ ALT_CLKMGR_BYPASS_PERPLLSRC_SET_MSK : ALT_CLKMGR_BYPASS_PERPLL_SET_MSK;
+ // set bypass bit and optionally the source select bit
+#endif
+ status = ALT_E_SUCCESS;
+ }
+
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_BYPASS_ADDR) &
+ (ALT_CLKMGR_BYPASS_SDRPLL_CLR_MSK & ALT_CLKMGR_BYPASS_SDRPLLSRC_CLR_MSK);
+ temp |= (use_input_mux) ? ALT_CLKMGR_BYPASS_SDRPLL_SET_MSK |
+ ALT_CLKMGR_BYPASS_SDRPLLSRC_SET_MSK : ALT_CLKMGR_BYPASS_SDRPLL_SET_MSK;
+ // set bypass bit and optionally the source select bit
+ alt_write_word(ALT_CLKMGR_BYPASS_ADDR, temp);
+ status = ALT_E_SUCCESS;
+ }
+ return status;
+}
+
+
+/****************************************************************************************/
+/* alt_clk_pll_is_bypassed() returns whether the specified PLL is in bypass or not. */
+/* Bypass is a special state where the PLL VCO and the C0-C5 counters are bypassed */
+/* and not in the circuit. Either the Osc1 clock input or the input chosen by the */
+/* input mux may be selected to be operational in the bypass state. All changes to */
+/* the PLL VCO must be made in bypass mode to avoid the potential of producing clock */
+/* glitches which may affect downstream clock dividers and peripherals. */
+/****************************************************************************************/
+
+ALT_STATUS_CODE alt_clk_pll_is_bypassed(ALT_CLK_t pll)
+{
+ ALT_STATUS_CODE status = ALT_E_BAD_ARG;
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ status = (ALT_CLKMGR_CTL_SAFEMOD_GET(alt_read_word(ALT_CLKMGR_CTL_ADDR))
+ || ALT_CLKMGR_BYPASS_MAINPLL_GET(alt_read_word(ALT_CLKMGR_BYPASS_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ status = (ALT_CLKMGR_CTL_SAFEMOD_GET(alt_read_word(ALT_CLKMGR_CTL_ADDR))
+ || ALT_CLKMGR_BYPASS_PERPLL_GET(alt_read_word(ALT_CLKMGR_BYPASS_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ status = (ALT_CLKMGR_CTL_SAFEMOD_GET(alt_read_word(ALT_CLKMGR_CTL_ADDR))
+ || ALT_CLKMGR_BYPASS_SDRPLL_GET(alt_read_word(ALT_CLKMGR_BYPASS_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ }
+ return status;
+}
+
+
+/****************************************************************************************/
+/* alt_clk_pll_source_get() returns the current input of the specified PLL. */
+/****************************************************************************************/
+
+ALT_CLK_t alt_clk_pll_source_get(ALT_CLK_t pll)
+{
+ ALT_CLK_t ret = ALT_CLK_UNKNOWN;
+ uint32_t temp;
+
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ ret = ALT_CLK_IN_PIN_OSC1;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ // three possible clock sources for the peripheral PLL
+ temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
+ {
+ ret = ALT_CLK_IN_PIN_OSC1;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
+ {
+ ret = ALT_CLK_IN_PIN_OSC2;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
+ {
+ ret = ALT_CLK_F2H_PERIPH_REF;
+ }
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ // three possible clock sources for the SDRAM PLL
+ temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
+ if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
+ {
+ ret = ALT_CLK_IN_PIN_OSC1;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
+ {
+ ret = ALT_CLK_IN_PIN_OSC2;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
+ {
+ ret = ALT_CLK_F2H_SDRAM_REF;
+ }
+ }
+ return ret;
+}
+
+//
+// alt_clk_clock_disable() disables the specified clock. Once the clock is disabled,
+// its clock signal does not propagate to its clocked elements.
+//
+ALT_STATUS_CODE alt_clk_clock_disable(ALT_CLK_t clk)
+{
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+
+ switch (clk)
+ {
+ // For PLLs, put them in bypass mode.
+ case ALT_CLK_MAIN_PLL:
+ case ALT_CLK_PERIPHERAL_PLL:
+ case ALT_CLK_SDRAM_PLL:
+ status = alt_clk_pll_bypass_enable(clk, false);
+ break;
+
+ // Clocks that originate at the Main PLL.
+ case ALT_CLK_L4_MAIN:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MAINCLK_SET_MSK);
+ break;
+ case ALT_CLK_L3_MP:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L3MPCLK_SET_MSK);
+ break;
+ case ALT_CLK_L4_MP:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK);
+ break;
+ case ALT_CLK_L4_SP:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG_AT:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGATCLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGCLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG_TRACE:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG_TIMER:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTMRCLK_SET_MSK);
+ break;
+ case ALT_CLK_CFG:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_CFGCLK_SET_MSK);
+ break;
+ case ALT_CLK_H2F_USER0:
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_SET_MSK);
+ break;
+
+ // Clocks that originate at the Peripheral PLL.
+ case ALT_CLK_EMAC0:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC0CLK_SET_MSK);
+ break;
+ case ALT_CLK_EMAC1:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC1CLK_SET_MSK);
+ break;
+ case ALT_CLK_USB_MP:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK);
+ break;
+ case ALT_CLK_SPI_M:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK);
+ break;
+ case ALT_CLK_CAN0:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK);
+ break;
+ case ALT_CLK_CAN1:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK);
+ break;
+ case ALT_CLK_GPIO_DB:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK);
+ break;
+ case ALT_CLK_H2F_USER1:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_SET_MSK);
+ break;
+ case ALT_CLK_SDMMC:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK);
+ break;
+ case ALT_CLK_NAND_X:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
+ // gate nand_clk off before nand_x_clk.
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
+ break;
+ case ALT_CLK_NAND:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
+ break;
+ case ALT_CLK_QSPI:
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
+ break;
+
+ // Clocks that originate at the SDRAM PLL.
+ case ALT_CLK_DDR_DQS:
+ alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_SET_MSK);
+ break;
+ case ALT_CLK_DDR_2X_DQS:
+ alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_SET_MSK);
+ break;
+ case ALT_CLK_DDR_DQ:
+ alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_SET_MSK);
+ break;
+ case ALT_CLK_H2F_USER2:
+ alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_SET_MSK);
+ break;
+
+ default:
+ status = ALT_E_BAD_ARG;
+ break;
+ }
+
+ return status;
+}
+
+
+//
+// alt_clk_clock_enable() enables the specified clock. Once the clock is enabled, its
+// clock signal propagates to its elements.
+//
+ALT_STATUS_CODE alt_clk_clock_enable(ALT_CLK_t clk)
+{
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+
+ switch (clk)
+ {
+ // For PLLs, take them out of bypass mode.
+ case ALT_CLK_MAIN_PLL:
+ case ALT_CLK_PERIPHERAL_PLL:
+ case ALT_CLK_SDRAM_PLL:
+ status = alt_clk_pll_bypass_disable(clk);
+ break;
+
+ // Clocks that originate at the Main PLL.
+ case ALT_CLK_L4_MAIN:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MAINCLK_SET_MSK);
+ break;
+ case ALT_CLK_L3_MP:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L3MPCLK_SET_MSK);
+ break;
+ case ALT_CLK_L4_MP:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK);
+ break;
+ case ALT_CLK_L4_SP:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG_AT:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGATCLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGCLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG_TRACE:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_SET_MSK);
+ break;
+ case ALT_CLK_DBG_TIMER:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTMRCLK_SET_MSK);
+ break;
+ case ALT_CLK_CFG:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_CFGCLK_SET_MSK);
+ break;
+ case ALT_CLK_H2F_USER0:
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_SET_MSK);
+ break;
+
+ // Clocks that originate at the Peripheral PLL.
+ case ALT_CLK_EMAC0:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC0CLK_SET_MSK);
+ break;
+ case ALT_CLK_EMAC1:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC1CLK_SET_MSK);
+ break;
+ case ALT_CLK_USB_MP:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK);
+ break;
+ case ALT_CLK_SPI_M:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK);
+ break;
+ case ALT_CLK_CAN0:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK);
+ break;
+ case ALT_CLK_CAN1:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK);
+ break;
+ case ALT_CLK_GPIO_DB:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK);
+ break;
+ case ALT_CLK_H2F_USER1:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_SET_MSK);
+ break;
+ case ALT_CLK_SDMMC:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK);
+ break;
+ case ALT_CLK_NAND_X:
+ // implementation detail - should ALK_CLK_NAND be gated off here before enabling ALT_CLK_NAND_X?
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
+ // implementation detail - should this wait be enforced here?
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
+ break;
+ case ALT_CLK_NAND:
+ // enabling ALT_CLK_NAND always implies enabling ALT_CLK_NAND_X first
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
+ // gate nand_x_clk on at least 8 MCU clocks before nand_clk
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
+ break;
+ case ALT_CLK_QSPI:
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
+ break;
+
+ // Clocks that originate at the SDRAM PLL.
+ case ALT_CLK_DDR_DQS:
+ alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_SET_MSK);
+ break;
+ case ALT_CLK_DDR_2X_DQS:
+ alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_SET_MSK);
+ break;
+ case ALT_CLK_DDR_DQ:
+ alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_SET_MSK);
+ break;
+ case ALT_CLK_H2F_USER2:
+ alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_SET_MSK);
+ break;
+
+ default:
+ status = ALT_E_BAD_ARG;
+ break;
+ }
+
+ return status;
+}
+
+//
+// alt_clk_is_enabled() returns whether the specified clock is enabled or not.
+//
+ALT_STATUS_CODE alt_clk_is_enabled(ALT_CLK_t clk)
+{
+ ALT_STATUS_CODE status = ALT_E_BAD_ARG;
+
+ switch (clk)
+ {
+ // For PLLs, this function checks if the PLL is bypassed or not.
+ case ALT_CLK_MAIN_PLL:
+ case ALT_CLK_PERIPHERAL_PLL:
+ case ALT_CLK_SDRAM_PLL:
+ status = (alt_clk_pll_is_bypassed(clk) != ALT_E_TRUE);
+ break;
+
+ // These clocks are not gated, so must return a ALT_E_BAD_ARG type error.
+ case ALT_CLK_MAIN_PLL_C0:
+ case ALT_CLK_MAIN_PLL_C1:
+ case ALT_CLK_MAIN_PLL_C2:
+ case ALT_CLK_MAIN_PLL_C3:
+ case ALT_CLK_MAIN_PLL_C4:
+ case ALT_CLK_MAIN_PLL_C5:
+ case ALT_CLK_MPU:
+ case ALT_CLK_MPU_L2_RAM:
+ case ALT_CLK_MPU_PERIPH:
+ case ALT_CLK_L3_MAIN:
+ case ALT_CLK_L3_SP:
+ case ALT_CLK_DBG_BASE:
+ case ALT_CLK_MAIN_QSPI:
+ case ALT_CLK_MAIN_NAND_SDMMC:
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ case ALT_CLK_SDRAM_PLL_C0:
+ case ALT_CLK_SDRAM_PLL_C1:
+ case ALT_CLK_SDRAM_PLL_C2:
+ case ALT_CLK_SDRAM_PLL_C5:
+ status = ALT_E_BAD_ARG;
+ break;
+
+ // Clocks that originate at the Main PLL.
+ case ALT_CLK_L4_MAIN:
+ status = (ALT_CLKMGR_MAINPLL_EN_L4MAINCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_L3_MP:
+ status = (ALT_CLKMGR_MAINPLL_EN_L3MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_L4_MP:
+ status = (ALT_CLKMGR_MAINPLL_EN_L4MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_L4_SP:
+ status = (ALT_CLKMGR_MAINPLL_EN_L4SPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_DBG_AT:
+ status = (ALT_CLKMGR_MAINPLL_EN_DBGATCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_DBG:
+ status = (ALT_CLKMGR_MAINPLL_EN_DBGCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_DBG_TRACE:
+ status = (ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_DBG_TIMER:
+ status = (ALT_CLKMGR_MAINPLL_EN_DBGTMRCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_CFG:
+ status = (ALT_CLKMGR_MAINPLL_EN_CFGCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_H2F_USER0:
+ status = (ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+
+ // Clocks that originate at the Peripheral PLL.
+ case ALT_CLK_EMAC0:
+ status = (ALT_CLKMGR_PERPLL_EN_EMAC0CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_EMAC1:
+ status = (ALT_CLKMGR_PERPLL_EN_EMAC1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_USB_MP:
+ status = (ALT_CLKMGR_PERPLL_EN_USBCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_SPI_M:
+ status = (ALT_CLKMGR_PERPLL_EN_SPIMCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_CAN0:
+ status = (ALT_CLKMGR_PERPLL_EN_CAN0CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_CAN1:
+ status = (ALT_CLKMGR_PERPLL_EN_CAN1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_GPIO_DB:
+ status = (ALT_CLKMGR_PERPLL_EN_GPIOCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_H2F_USER1:
+ status = (ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+
+ // Clocks that may originate at the Main PLL, the Peripheral PLL, or the FPGA.
+ case ALT_CLK_SDMMC:
+ status = (ALT_CLKMGR_PERPLL_EN_SDMMCCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_NAND_X:
+ status = (ALT_CLKMGR_PERPLL_EN_NANDXCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_NAND:
+ status = (ALT_CLKMGR_PERPLL_EN_NANDCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_QSPI:
+ status = (ALT_CLKMGR_PERPLL_EN_QSPICLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+
+ // Clocks that originate at the SDRAM PLL.
+ case ALT_CLK_DDR_DQS:
+ status = (ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_DDR_2X_DQS:
+ status = (ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_DDR_DQ:
+ status = (ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+ case ALT_CLK_H2F_USER2:
+ status = (ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
+ ? ALT_E_TRUE : ALT_E_FALSE;
+ break;
+
+ default:
+ status = ALT_E_BAD_ARG;
+ break;
+
+ }
+
+ return status;
+}
+
+//
+// alt_clk_source_get() gets the input reference clock source selection value for the
+// specified clock or PLL.
+//
+ALT_CLK_t alt_clk_source_get(ALT_CLK_t clk)
+{
+ ALT_CLK_t ret = ALT_CLK_UNKNOWN;
+ uint32_t temp;
+
+ switch (clk)
+ {
+ // Potential external clock sources.
+ // these clock entities are their own source
+ case ALT_CLK_IN_PIN_OSC1:
+ case ALT_CLK_IN_PIN_OSC2:
+ case ALT_CLK_F2H_PERIPH_REF:
+ case ALT_CLK_F2H_SDRAM_REF:
+ case ALT_CLK_IN_PIN_JTAG:
+ case ALT_CLK_IN_PIN_ULPI0:
+ case ALT_CLK_IN_PIN_ULPI1:
+ case ALT_CLK_IN_PIN_EMAC0_RX:
+ case ALT_CLK_IN_PIN_EMAC1_RX:
+ ret = clk;
+ break;
+
+ // Phase-Locked Loops.
+ case ALT_CLK_MAIN_PLL:
+ case ALT_CLK_OSC1:
+ ret = ALT_CLK_IN_PIN_OSC1;
+ break;
+ case ALT_CLK_PERIPHERAL_PLL:
+ ret = alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL);
+ break;
+ case ALT_CLK_SDRAM_PLL:
+ ret = alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL);
+ break;
+
+ // Main Clock Group.
+ case ALT_CLK_MAIN_PLL_C0:
+ case ALT_CLK_MAIN_PLL_C1:
+ case ALT_CLK_MAIN_PLL_C2:
+ case ALT_CLK_MAIN_PLL_C3:
+ case ALT_CLK_MAIN_PLL_C4:
+ case ALT_CLK_MAIN_PLL_C5:
+ // check bypass, return either osc1 or PLL ID
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL;
+ break;
+
+ case ALT_CLK_MPU_PERIPH:
+ case ALT_CLK_MPU_L2_RAM:
+ case ALT_CLK_MPU:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C0;
+ break;
+
+ case ALT_CLK_L4_MAIN:
+ case ALT_CLK_L3_MAIN:
+ case ALT_CLK_L3_MP:
+ case ALT_CLK_L3_SP:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C1;
+ break;
+
+ case ALT_CLK_L4_MP:
+ // read the state of the L4_mp source bit
+ if ((ALT_CLKMGR_MAINPLL_L4SRC_L4MP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR)))
+ == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_MAINPLL)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C1;
+ }
+ else
+ {
+ // if the clock comes from periph_base_clk
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C4;
+ }
+ break;
+
+ case ALT_CLK_L4_SP:
+ // read the state of the source bit
+ if ((ALT_CLKMGR_MAINPLL_L4SRC_L4SP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR)))
+ == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_MAINPLL)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C1;
+ }
+ else
+ {
+ // if the clock comes from periph_base_clk
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C4;
+ }
+ break;
+
+ case ALT_CLK_DBG_BASE:
+ case ALT_CLK_DBG_AT:
+ case ALT_CLK_DBG_TRACE:
+ case ALT_CLK_DBG_TIMER:
+ case ALT_CLK_DBG:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C2;
+ break;
+ case ALT_CLK_MAIN_QSPI:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C3;
+ break;
+ case ALT_CLK_MAIN_NAND_SDMMC:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C4;
+ break;
+ case ALT_CLK_CFG:
+ case ALT_CLK_H2F_USER0:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C5;
+ break;
+
+ // Peripherals Clock Group
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ // if the clock comes from periph_base_clk
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL;
+ break;
+
+ case ALT_CLK_EMAC0:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C0;
+ break;
+
+ case ALT_CLK_EMAC1:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C1;
+ break;
+
+ case ALT_CLK_USB_MP:
+ case ALT_CLK_SPI_M:
+ case ALT_CLK_CAN0:
+ case ALT_CLK_CAN1:
+ case ALT_CLK_GPIO_DB:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C4;
+ break;
+
+ case ALT_CLK_H2F_USER1:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C5;
+ break;
+
+ case ALT_CLK_SDMMC:
+ temp = ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_F2S_PERIPH_REF_CLK)
+ {
+ ret = ALT_CLK_F2H_PERIPH_REF;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C4;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C3;
+ }
+ break;
+
+ case ALT_CLK_NAND_X:
+ case ALT_CLK_NAND:
+ temp = ALT_CLKMGR_PERPLL_SRC_NAND_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_F2S_PERIPH_REF_CLK)
+ {
+ ret = ALT_CLK_F2H_PERIPH_REF;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C4;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C3;
+ }
+ break;
+
+ case ALT_CLK_QSPI:
+ temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_F2S_PERIPH_REF_CLK)
+ {
+ ret = ALT_CLK_F2H_PERIPH_REF;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
+ ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C3;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
+ {
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C2;
+ }
+ break;
+
+ // SDRAM Clock Group
+ case ALT_CLK_SDRAM_PLL_C0:
+ case ALT_CLK_SDRAM_PLL_C1:
+ case ALT_CLK_SDRAM_PLL_C2:
+ case ALT_CLK_SDRAM_PLL_C3:
+ case ALT_CLK_SDRAM_PLL_C4:
+ case ALT_CLK_SDRAM_PLL_C5:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) : ALT_CLK_SDRAM_PLL;
+ break;
+ case ALT_CLK_DDR_DQS:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) : ALT_CLK_SDRAM_PLL_C0;
+ break;
+ case ALT_CLK_DDR_2X_DQS:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) : ALT_CLK_SDRAM_PLL_C1;
+ break;
+ case ALT_CLK_DDR_DQ:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) : ALT_CLK_SDRAM_PLL_C2;
+ break;
+ case ALT_CLK_H2F_USER2:
+ ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
+ alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) : ALT_CLK_SDRAM_PLL_C5;
+ break;
+
+ // Clock Output Pins
+ case ALT_CLK_OUT_PIN_EMAC0_TX:
+ case ALT_CLK_OUT_PIN_EMAC1_TX:
+ case ALT_CLK_OUT_PIN_SDMMC:
+ case ALT_CLK_OUT_PIN_I2C0_SCL:
+ case ALT_CLK_OUT_PIN_I2C1_SCL:
+ case ALT_CLK_OUT_PIN_I2C2_SCL:
+ case ALT_CLK_OUT_PIN_I2C3_SCL:
+ case ALT_CLK_OUT_PIN_SPIM0:
+ case ALT_CLK_OUT_PIN_SPIM1:
+ case ALT_CLK_OUT_PIN_QSPI:
+ ret = ALT_CLK_UNKNOWN;
+ break;
+
+ default:
+ ret = ALT_CLK_UNKNOWN;
+ break;
+ }
+
+ return ret;
+}
+
+//
+// alt_clk_source_set() sets the specified clock's input reference clock source
+// selection to the specified input. It does not handle gating the specified clock
+// off and back on, those are covered in other functions in this API, but it does
+// verify that the clock is off before changing the divider or PLL. Note that the PLL
+// must have regained phase-lock before being the bypass is disabled.
+//
+ALT_STATUS_CODE alt_clk_source_set(ALT_CLK_t clk, ALT_CLK_t ref_clk)
+{
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+ uint32_t temp;
+
+ if (ALT_CLK_MAIN_PLL == clk)
+ {
+ if ((ref_clk == ALT_CLK_IN_PIN_OSC1) || (ref_clk == ALT_CLK_OSC1))
+ {
+ // ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ status = ALT_E_BAD_ARG;
+ }
+ }
+ else if (ALT_CLK_PERIPHERAL_PLL == clk)
+ {
+ // the PLL must be bypassed before getting here
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+ temp &= ALT_CLKMGR_PERPLL_VCO_PSRC_CLR_MSK;
+
+ if ((ref_clk == ALT_CLK_IN_PIN_OSC1) || (ref_clk == ALT_CLK_OSC1))
+ {
+ temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1);
+ alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
+ }
+ else if (ref_clk == ALT_CLK_IN_PIN_OSC2)
+ {
+ temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2);
+ alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
+ }
+ else if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
+ {
+ temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF);
+ alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
+ }
+ else
+ {
+ status = ALT_E_INV_OPTION;
+ }
+ }
+ else if (ALT_CLK_SDRAM_PLL == clk)
+ {
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
+ temp &= ALT_CLKMGR_SDRPLL_VCO_SSRC_CLR_MSK;
+
+ if ((ref_clk == ALT_CLK_IN_PIN_OSC1) || (ref_clk == ALT_CLK_OSC1))
+ {
+ temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1);
+ alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
+ }
+ else if (ref_clk == ALT_CLK_IN_PIN_OSC2)
+ {
+ temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2);
+ alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
+ }
+ else if (ref_clk == ALT_CLK_F2H_SDRAM_REF)
+ {
+ temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF);
+ alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
+ }
+ else
+ {
+ status = ALT_E_INV_OPTION;
+ }
+ }
+ else if ( ALT_CLK_L4_MP == clk)
+ {
+ // clock is gated off
+ if (ref_clk == ALT_CLK_MAIN_PLL_C1)
+ {
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK);
+ }
+ else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C4)
+ {
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK);
+ }
+ else
+ {
+ status = ALT_E_INV_OPTION;
+ }
+ }
+ else if ( ALT_CLK_L4_SP == clk)
+ {
+ if (ref_clk == ALT_CLK_MAIN_PLL_C1)
+ {
+ alt_clrbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK);
+ }
+ else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C4)
+ {
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK);
+ }
+ else
+ {
+ status = ALT_E_INV_OPTION;
+ }
+ }
+ else if (ALT_CLK_SDMMC == clk)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
+ temp &= ALT_CLKMGR_PERPLL_SRC_SDMMC_CLR_MSK;
+
+ if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_SDMMC_SET(ALT_CLKMGR_PERPLL_SRC_SDMMC_E_F2S_PERIPH_REF_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else if ((ref_clk == ALT_CLK_MAIN_PLL_C4) || (ref_clk == ALT_CLK_MAIN_NAND_SDMMC))
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_SDMMC_SET(ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C3)
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_SDMMC_SET(ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else
+ {
+ status = ALT_E_INV_OPTION;
+ }
+ }
+ else if ((ALT_CLK_NAND_X == clk) || ( ALT_CLK_NAND == clk))
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
+ temp &= ALT_CLKMGR_PERPLL_SRC_NAND_CLR_MSK;
+
+ if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_NAND_SET(ALT_CLKMGR_PERPLL_SRC_NAND_E_F2S_PERIPH_REF_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else if ((ref_clk == ALT_CLK_MAIN_PLL_C4) || (ref_clk == ALT_CLK_MAIN_NAND_SDMMC))
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_NAND_SET(ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C3)
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_NAND_SET(ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else
+ {
+ status = ALT_E_INV_OPTION;
+ }
+ }
+ else if (ALT_CLK_QSPI == clk)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
+ temp &= ALT_CLKMGR_PERPLL_SRC_QSPI_CLR_MSK;
+
+ if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_QSPI_SET(ALT_CLKMGR_PERPLL_SRC_QSPI_E_F2S_PERIPH_REF_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else if ((ref_clk == ALT_CLK_MAIN_PLL_C3) || (ref_clk == ALT_CLK_MAIN_QSPI))
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_QSPI_SET(ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C2)
+ {
+ temp |= ALT_CLKMGR_PERPLL_SRC_QSPI_SET(ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
+ }
+ else
+ {
+ status = ALT_E_INV_OPTION;
+ }
+ }
+
+ return status;
+}
+
+//
+// alt_clk_ext_clk_freq_set() specifies the frequency of the external clock source as
+// a measure of Hz. This value is stored in a static array and used for calculations.
+// The supplied frequency should be within the Fmin and Fmax values allowed for the
+// external clock source.
+//
+ALT_STATUS_CODE alt_clk_ext_clk_freq_set(ALT_CLK_t clk, alt_freq_t freq)
+{
+ ALT_STATUS_CODE status = ALT_E_BAD_ARG;
+
+ if ((clk == ALT_CLK_IN_PIN_OSC1) || (clk == ALT_CLK_OSC1)) // two names for one input
+ {
+ if ((freq >= alt_ext_clk_paramblok.clkosc1.freqmin) && (freq <= alt_ext_clk_paramblok.clkosc1.freqmax))
+ {
+ alt_ext_clk_paramblok.clkosc1.freqcur = freq;
+ status = ALT_E_SUCCESS;
+ }
+ else
+ {
+ status = ALT_E_ARG_RANGE;
+ }
+ }
+ else if (clk == ALT_CLK_IN_PIN_OSC2) // the other clock input pin
+ {
+ if ((freq >= alt_ext_clk_paramblok.clkosc2.freqmin) && (freq <= alt_ext_clk_paramblok.clkosc2.freqmax))
+ {
+ alt_ext_clk_paramblok.clkosc2.freqcur = freq;
+ status = ALT_E_SUCCESS;
+ }
+ else
+ {
+ status = ALT_E_ARG_RANGE;
+ }
+ }
+ else if (clk == ALT_CLK_F2H_PERIPH_REF) // clock from the FPGA
+ {
+ if ((freq >= alt_ext_clk_paramblok.periph.freqmin) && (freq <= alt_ext_clk_paramblok.periph.freqmax))
+ {
+ alt_ext_clk_paramblok.periph.freqcur = freq;
+ status = ALT_E_SUCCESS;
+ }
+ else
+ {
+ status = ALT_E_ARG_RANGE;
+ }
+ }
+ else if (clk == ALT_CLK_F2H_SDRAM_REF) // clock from the FPGA SDRAM
+ {
+ if ((freq >= alt_ext_clk_paramblok.sdram.freqmin) && (freq <= alt_ext_clk_paramblok.sdram.freqmax))
+ {
+ alt_ext_clk_paramblok.sdram.freqcur = freq;
+ status = ALT_E_SUCCESS;
+ }
+ else
+ {
+ status = ALT_E_ARG_RANGE;
+ }
+ }
+ else
+ {
+ status = ALT_E_BAD_ARG;
+ }
+
+ return status;
+}
+
+
+//
+// alt_clk_ext_clk_freq_get returns the frequency of the external clock source as
+// a measure of Hz. This value is stored in a static array.
+//
+alt_freq_t alt_clk_ext_clk_freq_get(ALT_CLK_t clk)
+{
+ uint32_t ret = 0;
+
+ if ((clk == ALT_CLK_IN_PIN_OSC1) || (clk == ALT_CLK_OSC1)) // two names for one input
+ {
+ ret = alt_ext_clk_paramblok.clkosc1.freqcur;
+ }
+ else if (clk == ALT_CLK_IN_PIN_OSC2)
+ {
+ ret = alt_ext_clk_paramblok.clkosc2.freqcur;
+ }
+ else if (clk == ALT_CLK_F2H_PERIPH_REF) // clock from the FPGA
+ {
+ ret = alt_ext_clk_paramblok.periph.freqcur;
+ }
+ else if (clk == ALT_CLK_F2H_SDRAM_REF) // clock from the FPGA
+ {
+ ret = alt_ext_clk_paramblok.sdram.freqcur;
+ }
+ return ret;
+}
+
+
+//
+// alt_clk_pll_cfg_get() returns the current PLL configuration.
+//
+ALT_STATUS_CODE alt_clk_pll_cfg_get(ALT_CLK_t pll, ALT_CLK_PLL_CFG_t * pll_cfg)
+{
+ ALT_STATUS_CODE ret = ALT_E_ERROR; // return value
+ uint32_t temp; // temp variable
+
+ if (pll_cfg == NULL)
+ {
+ ret = ALT_E_BAD_ARG;
+ return ret;
+ }
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
+ pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC1;
+ pll_cfg->mult = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp);
+ pll_cfg->div = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp);
+
+ // Get the C0-C5 divider values:
+ pll_cfg->cntrs[0] = ALT_CLKMGR_MAINPLL_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR));
+ // C0 - mpu_clk
+
+ pll_cfg->cntrs[1] = ALT_CLKMGR_MAINPLL_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR));
+ // C1 - main_clk
+
+ pll_cfg->cntrs[2] = ALT_CLKMGR_MAINPLL_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR));
+ // C2 - dbg_base_clk
+
+ pll_cfg->cntrs[3] = ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR));
+ // C3 - main_qspi_clk
+
+ pll_cfg->cntrs[4] = ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR));
+ // C4 - main_nand_sdmmc_clk
+
+ pll_cfg->cntrs[5] = ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR));
+ // C5 - cfg_s2f_user0_clk aka cfg_h2f_user0_clk
+
+ // The Main PLL C0-C5 outputs have no phase shift capabilities :
+ pll_cfg->pshift[0] = pll_cfg->pshift[1] = pll_cfg->pshift[2] =
+ pll_cfg->pshift[3] = pll_cfg->pshift[4] = pll_cfg->pshift[5] = 0;
+ ret = ALT_E_SUCCESS;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR));
+ if (temp <= 2)
+ {
+ if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
+ {
+ pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC1;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
+ {
+ pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC2;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
+ {
+ pll_cfg->ref_clk = ALT_CLK_F2H_PERIPH_REF;
+ }
+
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+ pll_cfg->mult = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp);
+ pll_cfg->div = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp);
+
+ // Get the C0-C5 divider values:
+ pll_cfg->cntrs[0] = ALT_CLKMGR_PERPLL_EMAC0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR));
+ // C0 - emac0_clk
+
+ pll_cfg->cntrs[1] = ALT_CLKMGR_PERPLL_EMAC1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR));
+ // C1 - emac1_clk
+
+ pll_cfg->cntrs[2] = ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR));
+ // C2 - periph_qspi_clk
+
+ pll_cfg->cntrs[3] = ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR));
+ // C3 - periph_nand_sdmmc_clk
+
+ pll_cfg->cntrs[4] = ALT_CLKMGR_PERPLL_PERBASECLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR));
+ // C4 - periph_base_clk
+
+ pll_cfg->cntrs[5] = ALT_CLKMGR_PERPLL_S2FUSER1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR));
+ // C5 - s2f_user1_clk
+
+ // The Peripheral PLL C0-C5 outputs have no phase shift capabilities :
+ pll_cfg->pshift[0] = pll_cfg->pshift[1] = pll_cfg->pshift[2] =
+ pll_cfg->pshift[3] = pll_cfg->pshift[4] = pll_cfg->pshift[5] = 0;
+ ret = ALT_E_SUCCESS;
+ }
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
+ if (temp <= 2)
+ {
+ if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
+ {
+ pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC1;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
+ {
+ pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC2;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
+ {
+ pll_cfg->ref_clk = ALT_CLK_F2H_SDRAM_REF;
+ }
+
+ pll_cfg->mult = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
+ pll_cfg->div = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
+
+ // Get the C0-C5 divider values:
+ pll_cfg->cntrs[0] = ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR));
+ pll_cfg->pshift[0] = ALT_CLKMGR_SDRPLL_DDRDQSCLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR));
+ // C0 - ddr_dqs_clk
+
+ pll_cfg->cntrs[1] = ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR));
+ pll_cfg->pshift[1] = ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR));
+ // C1 - ddr_2x_dqs_clk
+
+ pll_cfg->cntrs[2] = ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR));
+ pll_cfg->pshift[2] = ALT_CLKMGR_SDRPLL_DDRDQCLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR));
+ // C2 - ddr_dq_clk
+
+ pll_cfg->cntrs[3] = pll_cfg->cntrs[4] = pll_cfg->pshift[3] = pll_cfg->pshift[4] = 0;
+ // C3 & C4 outputs don't exist on the SDRAM PLL
+
+ pll_cfg->cntrs[5] = ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR));
+ pll_cfg->pshift[5] = ALT_CLKMGR_SDRPLL_S2FUSER2CLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR));
+ // C5 - s2f_user2_clk or h2f_user2_clk
+
+ ret = ALT_E_SUCCESS;
+ }
+ }
+
+ return ret;
+}
+
+
+//
+// alt_clk_pll_cfg_set() sets the PLL configuration using the configuration parameters
+// specified in pll_cfg.
+//
+ALT_STATUS_CODE alt_clk_pll_cfg_set(ALT_CLK_t pll, const ALT_CLK_PLL_CFG_t * pll_cfg)
+{
+ if (pll_cfg == NULL)
+ {
+ return ALT_E_BAD_ARG;
+ }
+
+ if (alt_clk_pll_is_bypassed(pll) != ALT_E_TRUE) // safe to write the PLL registers?
+ {
+ return ALT_E_ERROR;
+ }
+
+ ALT_STATUS_CODE ret = ALT_E_ERROR;
+ uint32_t temp;
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ temp = (ALT_CLKMGR_MAINPLL_VCO_NUMER_CLR_MSK & ALT_CLKMGR_MAINPLL_VCO_DENOM_CLR_MSK)
+ & alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
+ temp |= ALT_CLKMGR_MAINPLL_VCO_NUMER_SET(pll_cfg->mult) |
+ ALT_CLKMGR_MAINPLL_VCO_DENOM_SET(pll_cfg->div);
+
+ alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, temp);
+ alt_write_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR, pll_cfg->cntrs[0]);
+ alt_write_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR, pll_cfg->cntrs[1]);
+ alt_write_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR, pll_cfg->cntrs[2]);
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR, pll_cfg->cntrs[3]);
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR, pll_cfg->cntrs[4]);
+ alt_write_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR, pll_cfg->cntrs[5]);
+ ret = ALT_E_SUCCESS;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ temp = ALT_CLKMGR_PERPLL_VCO_NUMER_CLR_MSK & ALT_CLKMGR_PERPLL_VCO_DENOM_CLR_MSK
+ & ALT_CLKMGR_PERPLL_VCO_PSRC_CLR_MSK;
+ temp &= alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+ temp |= ALT_CLKMGR_PERPLL_VCO_NUMER_SET(pll_cfg->mult)
+ | ALT_CLKMGR_PERPLL_VCO_DENOM_SET(pll_cfg->div);
+
+ if ((pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC1) || (pll_cfg->ref_clk == ALT_CLK_OSC1))
+ {
+ temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1);
+ }
+ else if (pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC2)
+ {
+ temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2);
+ }
+ else if (pll_cfg->ref_clk == ALT_CLK_F2H_PERIPH_REF)
+ {
+ temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF);
+ }
+ else
+ {
+ return ret;
+ }
+
+ alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
+ alt_write_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR, pll_cfg->cntrs[0]);
+ alt_write_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR, pll_cfg->cntrs[1]);
+ alt_write_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR, pll_cfg->cntrs[2]);
+ alt_write_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, pll_cfg->cntrs[3]);
+ alt_write_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR, pll_cfg->cntrs[4]);
+ alt_write_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR, pll_cfg->cntrs[5]);
+ ret = ALT_E_SUCCESS;
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ // write the SDRAM PLL VCO Counter -----------------------------
+ temp = ALT_CLKMGR_SDRPLL_VCO_NUMER_CLR_MSK & ALT_CLKMGR_SDRPLL_VCO_DENOM_CLR_MSK
+ & ALT_CLKMGR_SDRPLL_VCO_SSRC_CLR_MSK; // make a mask
+ temp &= alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
+ temp |= ALT_CLKMGR_SDRPLL_VCO_NUMER_SET(pll_cfg->mult)
+ | ALT_CLKMGR_SDRPLL_VCO_DENOM_SET(pll_cfg->div)
+ | ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_SET_MSK;
+ // setting this bit aligns the output phase of the counters and prevents
+ // glitches and too-short clock periods when restarting.
+ // this bit is cleared at the end of this routine
+
+ if ((pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC1) || (pll_cfg->ref_clk == ALT_CLK_OSC1))
+ {
+ temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1);
+ }
+ else if (pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC2)
+ {
+ temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2);
+ }
+ else if (pll_cfg->ref_clk == ALT_CLK_F2H_PERIPH_REF)
+ {
+ temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF);
+ }
+ else
+ {
+ return ret;
+ }
+
+ alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
+
+ // write the SDRAM PLL C0 Divide Counter -----------------------------
+ temp = ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_SET(pll_cfg->cntrs[0])
+ | ALT_CLKMGR_SDRPLL_DDRDQSCLK_PHASE_SET(pll_cfg->pshift[0]);
+
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR, temp,
+ ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_DDRDQSCLK_PHASE_SET_MSK,
+ ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_LSB);
+
+ // write the SDRAM PLL C1 Divide Counter -----------------------------
+ if (ret == ALT_E_SUCCESS)
+ {
+ temp = ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_SET(pll_cfg->cntrs[1])
+ | ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_PHASE_SET(pll_cfg->pshift[1]);
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR, temp,
+ ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_PHASE_SET_MSK,
+ ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_LSB);
+ }
+
+ // write the SDRAM PLL C2 Divide Counter -----------------------------
+ if (ret == ALT_E_SUCCESS)
+ {
+ temp = ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_SET(pll_cfg->cntrs[2])
+ | ALT_CLKMGR_SDRPLL_DDRDQCLK_PHASE_SET(pll_cfg->pshift[2]);
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR, temp,
+ ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_DDRDQCLK_PHASE_SET_MSK,
+ ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_LSB);
+ }
+
+ // write the SDRAM PLL C5 Divide Counter -----------------------------
+ if (ret == ALT_E_SUCCESS)
+ {
+ temp = ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_SET(pll_cfg->cntrs[2])
+ | ALT_CLKMGR_SDRPLL_S2FUSER2CLK_PHASE_SET(pll_cfg->pshift[2]);
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR, temp,
+ ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_S2FUSER2CLK_PHASE_SET_MSK,
+ ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_LSB);
+ }
+
+ if (ret == ALT_E_SUCCESS)
+ {
+ alt_clrbits_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_SET_MSK);
+ // allow the phase multiplexer and output counter to leave reset
+ }
+ }
+
+ return ret;
+}
+
+
+//
+// alt_clk_pll_vco_cfg_get() returns the current PLL VCO frequency configuration.
+//
+ALT_STATUS_CODE alt_clk_pll_vco_cfg_get(ALT_CLK_t pll, uint32_t * mult, uint32_t * div)
+{
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+ uint32_t temp;
+
+ if ( (mult == NULL) || (div == NULL) )
+ {
+ return ALT_E_BAD_ARG;
+ }
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
+ *mult = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp) + 1;
+ *div = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp) + 1;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+ *mult = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp) + 1;
+ *div = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp) + 1;
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
+ *mult = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(temp) + 1;
+ *div = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(temp) + 1;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+
+ return status;
+}
+
+
+/****************************************************************************************/
+/* This enum enumerates a set of possible change methods that are available for use by */
+/* alt_clk_pll_vco_cfg_set() to change VCO parameter settings. */
+/****************************************************************************************/
+
+typedef enum ALT_CLK_PLL_VCO_CHG_METHOD_e
+{
+ ALT_VCO_CHG_NONE_VALID = 0, /* No valid method to change PLL
+ * VCO was found */
+ ALT_VCO_CHG_NOCHANGE = 0x00000001, /* Proposed new VCO values are the
+ * same as the old values */
+ ALT_VCO_CHG_NUM = 0x00000002, /* Can change the VCO multiplier
+ * alone */
+ ALT_VCO_CHG_NUM_BYP = 0x00000004, /* A VCO multiplier-only change will
+ * require putting the PLL in bypass */
+ ALT_VCO_CHG_DENOM = 0x00000008, /* Can change the VCO divider
+ * alone */
+ ALT_VCO_CHG_DENOM_BYP = 0x00000010, /* A VCO divider-only change will
+ * require putting the PLL in bypass */
+ ALT_VCO_CHG_NUM_DENOM = 0x00000020, /* Can change the clock multiplier
+ * first. then the clock divider */
+ ALT_VCO_CHG_NUM_DENOM_BYP = 0x00000040, /* Changing the clock multiplier first.
+ * then the clock divider will
+ * require putting the PLL in bypass */
+ ALT_VCO_CHG_DENOM_NUM = 0x00000080, /* Can change the clock divider first.
+ * then the clock multiplier */
+ ALT_VCO_CHG_DENOM_NUM_BYP = 0x00000100 /* Changing the clock divider first.
+ * then the clock multiplier will
+ * require putting the PLL in bypass */
+} ALT_CLK_PLL_VCO_CHG_METHOD_t;
+
+
+
+/****************************************************************************************/
+/* alt_clk_pll_vco_chg_methods_get() determines which possible methods to change the */
+/* VCO are allowed within the limits set by the maximum PLL multiplier and divider */
+/* values and by the upper and lower frequency limits of the PLL, and also determines */
+/* whether each of these changes can be made without the PLL losing lock, which */
+/* requires the PLL to be bypassed before making changes, and removed from bypass state */
+/* afterwards. */
+/****************************************************************************************/
+
+
+#define ALT_CLK_PLL_VCO_CHG_METHOD_TEST_MODE false
+ // used for testing writes to the PLL VCOs
+
+
+
+static ALT_CLK_PLL_VCO_CHG_METHOD_t alt_clk_pll_vco_chg_methods_get(ALT_CLK_t pll,
+ uint32_t mult, uint32_t div )
+{
+#if ALT_CLK_PLL_VCO_CHG_METHOD_TEST_MODE
+
+ // used for testing
+ return ALT_VCO_CHG_NOCHANGE;
+
+#else
+
+ // check PLL max value limits
+ if ( (mult == 0) || (mult > ALT_CLK_PLL_MULT_MAX)
+ || (div == 0) || (div > ALT_CLK_PLL_DIV_MAX)
+ )
+ {
+ return ALT_VCO_CHG_NONE_VALID;
+ }
+
+ ALT_CLK_PLL_VCO_CHG_METHOD_t ret = ALT_VCO_CHG_NONE_VALID;
+ uint32_t temp;
+ uint32_t numer;
+ uint32_t denom;
+ uint32_t freqmax;
+ uint32_t freqmin;
+ uint32_t inputfreq;
+ uint32_t guardband;
+ bool numerchg = false;
+ bool denomchg = false;
+ bool within_gb;
+
+ // gather data values according to PLL
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
+
+ numer = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp);
+ denom = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp);
+
+ freqmax = alt_pll_clk_paramblok.MainPLL_800.freqmax;
+ freqmin = alt_pll_clk_paramblok.MainPLL_800.freqmin;
+ guardband = alt_pll_clk_paramblok.MainPLL_800.guardband;
+
+ inputfreq = alt_ext_clk_paramblok.clkosc1.freqcur;
+ }
+
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+
+ numer = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp);
+ denom = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp);
+
+ freqmax = alt_pll_clk_paramblok.PeriphPLL_800.freqmax;
+ freqmin = alt_pll_clk_paramblok.PeriphPLL_800.freqmin;
+ guardband = alt_pll_clk_paramblok.PeriphPLL_800.guardband;
+
+ temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(temp);
+ if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
+ {
+ inputfreq = alt_ext_clk_paramblok.clkosc1.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
+ {
+ inputfreq = alt_ext_clk_paramblok.clkosc2.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
+ {
+ inputfreq = alt_ext_clk_paramblok.periph.freqcur;
+ }
+ else
+ {
+ return ret;
+ }
+ }
+
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
+
+ numer = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(temp);
+ denom = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(temp);
+
+ freqmax = alt_pll_clk_paramblok.SDRAMPLL_800.freqmax;
+ freqmin = alt_pll_clk_paramblok.SDRAMPLL_800.freqmin;
+ guardband = alt_pll_clk_paramblok.SDRAMPLL_800.guardband;
+
+ temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(temp);
+ if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
+ {
+ inputfreq = alt_ext_clk_paramblok.clkosc1.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
+ {
+ inputfreq = alt_ext_clk_paramblok.clkosc2.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
+ {
+ inputfreq = alt_ext_clk_paramblok.sdram.freqcur;
+ }
+ else
+ {
+ return ret;
+ }
+ }
+ else
+ {
+ return ret;
+ }
+
+ temp = mult * (inputfreq / div);
+ if ((temp <= freqmax) && (temp >= freqmin)) // are the final values within frequency limits?
+ {
+ numer++;
+ denom++;
+ numerchg = (mult != numer);
+ denomchg = (div != denom);
+
+ if (!numerchg && !denomchg)
+ {
+ ret = ALT_VCO_CHG_NOCHANGE;
+ }
+ else if (numerchg && !denomchg)
+ {
+ within_gb = alt_within_delta(numer, mult, guardband);
+ // check if change is within the guardband limits
+ temp = mult * (inputfreq / denom);
+ if ((temp <= freqmax) && (temp >= freqmin))
+ {
+ ret = ALT_VCO_CHG_NUM;
+ if (!within_gb) ret |= ALT_VCO_CHG_NUM_BYP;
+ }
+ }
+ else if (!numerchg && denomchg)
+ {
+ within_gb = alt_within_delta(denom, div, guardband);
+ temp = numer * (inputfreq / div);
+ if ((temp <= freqmax) && (temp >= freqmin))
+ {
+ ret = ALT_VCO_CHG_DENOM;
+ if (!within_gb)
+ {
+ ret |= ALT_VCO_CHG_DENOM_BYP;
+ }
+ }
+ }
+ else //numerchg && denomchg
+ {
+ within_gb = alt_within_delta(numer, mult, guardband);
+ temp = mult * (inputfreq / denom);
+ if ((temp <= freqmax) && (temp >= freqmin))
+ {
+ ret = ALT_VCO_CHG_NUM_DENOM;
+ if (!within_gb)
+ {
+ ret |= ALT_VCO_CHG_NUM_DENOM_BYP;
+ }
+ }
+ within_gb = alt_within_delta(denom, div, guardband);
+ temp = numer * (inputfreq / div);
+ if ((temp <= freqmax) && (temp >= freqmin))
+ {
+ ret = ALT_VCO_CHG_DENOM_NUM;
+ if (!within_gb)
+ {
+ ret |= ALT_VCO_CHG_DENOM_NUM_BYP;
+ }
+ }
+ }
+ }
+
+ return ret;
+#endif
+}
+
+
+/****************************************************************************************/
+/* alt_clk_pll_vco_cfg_set() sets the PLL VCO frequency configuration using the */
+/* supplied multiplier and divider arguments. alt_clk_pll_vco_chg_methods_get() */
+/* determines which methods are allowed by the limits set by the maximum multiplier */
+/* and divider values and by the upper and lower frequency limits of the PLL, and also */
+/* determines whether these changes can be made without requiring the PLL to be */
+/* bypassed. alt_clk_pll_vco_cfg_set() then carries out the actions required to effect */
+/* the method chosen to change the VCO settings. */
+/****************************************************************************************/
+
+ALT_STATUS_CODE alt_clk_pll_vco_cfg_set(ALT_CLK_t pll, uint32_t mult, uint32_t div)
+{
+ ALT_STATUS_CODE ret = ALT_E_ERROR;
+ ALT_CLK_PLL_VCO_CHG_METHOD_t method;
+ bool byp = false;
+ void *vaddr;
+ uint32_t numermask, denommask;
+ uint32_t numershift, denomshift;
+
+
+ method = alt_clk_pll_vco_chg_methods_get(pll, mult, div);
+
+ if (method == ALT_VCO_CHG_NONE_VALID)
+ {
+ ret = ALT_E_BAD_CLK;
+ }
+ else if (method == ALT_VCO_CHG_NOCHANGE)
+ {
+ ret = ALT_E_INV_OPTION;
+ }
+ else
+ {
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ vaddr = ALT_CLKMGR_MAINPLL_VCO_ADDR;
+ numermask = ALT_CLKMGR_MAINPLL_VCO_NUMER_SET_MSK;
+ denommask = ALT_CLKMGR_MAINPLL_VCO_DENOM_SET_MSK;
+ numershift = ALT_CLKMGR_MAINPLL_VCO_NUMER_LSB;
+ denomshift = ALT_CLKMGR_MAINPLL_VCO_DENOM_LSB;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ vaddr = ALT_CLKMGR_PERPLL_VCO_ADDR;
+ numermask = ALT_CLKMGR_PERPLL_VCO_NUMER_SET_MSK;
+ denommask = ALT_CLKMGR_PERPLL_VCO_DENOM_SET_MSK;
+ numershift = ALT_CLKMGR_PERPLL_VCO_NUMER_LSB;
+ denomshift = ALT_CLKMGR_PERPLL_VCO_DENOM_LSB;
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ vaddr = ALT_CLKMGR_SDRPLL_VCO_ADDR;
+ numermask = ALT_CLKMGR_SDRPLL_VCO_NUMER_SET_MSK;
+ denommask = ALT_CLKMGR_SDRPLL_VCO_DENOM_SET_MSK;
+ numershift = ALT_CLKMGR_SDRPLL_VCO_NUMER_LSB;
+ denomshift = ALT_CLKMGR_SDRPLL_VCO_DENOM_LSB;
+ }
+ else { return ALT_E_BAD_ARG; }
+
+ mult--;
+ div--;
+
+ if (method & ALT_VCO_CHG_NUM)
+ {
+ if (method & ALT_VCO_CHG_NUM_BYP)
+ {
+ alt_clk_pll_bypass_enable(pll, 0);
+ byp = true;
+ alt_clk_mgr_wait(vaddr, ALT_SW_MANAGED_CLK_WAIT_BYPASS);
+ }
+ alt_replbits_word(vaddr, numermask, mult << numershift);
+ }
+
+ else if (method & ALT_VCO_CHG_DENOM)
+ {
+ if (method & ALT_VCO_CHG_DENOM_BYP)
+ {
+ alt_clk_pll_bypass_enable(pll, 0);
+ byp = true;
+ }
+ alt_replbits_word(vaddr, denommask, div << denomshift);
+ }
+
+ else if (method & ALT_VCO_CHG_NUM_DENOM)
+ {
+ if (method & ALT_VCO_CHG_NUM_DENOM_BYP)
+ {
+ alt_clk_pll_bypass_enable(pll, 0);
+ byp = true;
+ }
+ alt_replbits_word(vaddr, numermask, mult << numershift);
+ if (!byp) // if PLL is not bypassed
+ {
+ ret = alt_clk_pll_lock_wait(ALT_CLK_MAIN_PLL, 1000);
+ // verify PLL is still locked or wait for it to lock again
+ }
+ alt_replbits_word(vaddr, denommask, div << denomshift);
+ }
+
+ else if (method & ALT_VCO_CHG_DENOM_NUM)
+ {
+ if (method & ALT_VCO_CHG_DENOM_NUM_BYP)
+ {
+ alt_clk_pll_bypass_enable(pll, 0);
+ byp = true;
+ }
+ alt_replbits_word(vaddr, numermask, mult << numershift);
+ if (!byp) // if PLL is not bypassed
+ {
+ ret = alt_clk_pll_lock_wait(ALT_CLK_MAIN_PLL, 1000);
+ // verify PLL is still locked or wait for it to lock again
+ }
+ alt_replbits_word(vaddr, denommask, div << denomshift);
+ }
+
+ ret = alt_clk_pll_lock_wait(ALT_CLK_MAIN_PLL, 1000);
+ // verify PLL is still locked or wait for it to lock again
+ if (byp)
+ {
+ alt_clk_pll_bypass_disable(pll);
+ alt_clk_mgr_wait(vaddr, ALT_SW_MANAGED_CLK_WAIT_BYPASS);
+ // wait for PLL to come out of bypass mode completely
+ }
+ }
+ return ret;
+}
+
+
+//
+// alt_clk_pll_vco_freq_get() gets the VCO frequency of the specified PLL.
+// Note that since there is at present no known way for software to obtain the speed
+// bin of the SoC or MPU that it is running on, the function below only deals with the
+// 800 MHz part. This may need to be revised in the future.
+//
+ALT_STATUS_CODE alt_clk_pll_vco_freq_get(ALT_CLK_t pll, alt_freq_t * freq)
+{
+ uint64_t temp1 = 0;
+ uint32_t temp;
+ uint32_t numer;
+ uint32_t denom;
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG;
+
+ if (freq == NULL)
+ {
+ return ret;
+ }
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
+ numer = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp);
+ denom = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp);
+ temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc1.freqcur;
+ temp1 *= (numer + 1);
+ temp1 /= (denom + 1);
+
+ if (temp1 <= UINT32_MAX)
+ {
+ temp = (alt_freq_t) temp1;
+ alt_pll_clk_paramblok.MainPLL_800.freqcur = temp;
+ // store this value in the parameter block table
+ *freq = temp;
+ // should NOT check value against PLL frequency limits
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+ numer = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp);
+ denom = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp);
+ temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(temp);
+ if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
+ {
+ temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc1.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
+ {
+ temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc2.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
+ {
+ temp1 = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
+ }
+
+ if (temp1 != 0)
+ {
+ temp1 *= (numer + 1);
+ temp1 /= (denom + 1);
+ if (temp1 <= UINT32_MAX)
+ {
+ temp = (alt_freq_t) temp1;
+ alt_pll_clk_paramblok.PeriphPLL_800.freqcur = temp;
+ // store this value in the parameter block table
+
+ *freq = temp;
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ } // this returns ALT_BAD_ARG if the source isn't known
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
+ numer = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(temp);
+ denom = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(temp);
+ temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(temp);
+ if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
+ {
+ temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc1.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
+ {
+ temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc2.freqcur;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
+ {
+ temp1 = (uint64_t) alt_ext_clk_paramblok.sdram.freqcur;
+ }
+
+ if (temp1 != 0)
+ {
+ temp1 *= (numer + 1);
+ temp1 /= (denom + 1);
+ if (temp1 <= UINT32_MAX)
+ {
+ temp = (alt_freq_t) temp1;
+ alt_pll_clk_paramblok.SDRAMPLL_800.freqcur = temp;
+ // store this value in the parameter block table
+
+ *freq = temp;
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ }
+ } // which returns ALT_BAD_ARG if the source isn't known
+
+ return ret;
+}
+
+//
+// Returns the current guard band range in effect for the PLL.
+//
+uint32_t alt_clk_pll_guard_band_get(ALT_CLK_t pll)
+{
+ uint32_t ret = 0;
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ ret = alt_pll_clk_paramblok.MainPLL_800.guardband;
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ ret = alt_pll_clk_paramblok.PeriphPLL_800.guardband;
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ ret = alt_pll_clk_paramblok.SDRAMPLL_800.guardband;
+ }
+ return ret;
+}
+
+//
+// clk_mgr_pll_guard_band_set() changes the guard band from its current value to permit
+// a more lenient or stringent policy to be in effect for the implementation of the
+// functions configuring PLL VCO frequency.
+//
+ALT_STATUS_CODE alt_clk_pll_guard_band_set(ALT_CLK_t pll, uint32_t guard_band)
+{
+ if ( (guard_band > UINT12_MAX) || (guard_band <= 0)
+ || (guard_band > ALT_GUARDBAND_LIMIT)
+ )
+ {
+ return ALT_E_ARG_RANGE;
+ }
+
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+
+ if (pll == ALT_CLK_MAIN_PLL)
+ {
+ alt_pll_clk_paramblok.MainPLL_800.guardband = guard_band;
+ //alt_pll_clk_paramblok.MainPLL_600.guardband = guard_band;
+ // ??? Don't know how to check the MPU speed bin yet, so only 800 MHz struct is used
+ }
+ else if (pll == ALT_CLK_PERIPHERAL_PLL)
+ {
+ alt_pll_clk_paramblok.PeriphPLL_800.guardband = guard_band;
+ //alt_pll_clk_paramblok.PeriphPLL_600.guardband = guard_band;
+ }
+ else if (pll == ALT_CLK_SDRAM_PLL)
+ {
+ alt_pll_clk_paramblok.SDRAMPLL_800.guardband = guard_band;
+ //alt_pll_clk_paramblok.SDRAMPLL_600.guardband = guard_band;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+
+ return status;
+}
+
+//
+// alt_clk_divider_get() gets configured divider value for the specified clock.
+//
+ALT_STATUS_CODE alt_clk_divider_get(ALT_CLK_t clk, uint32_t * div)
+{
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+ uint32_t temp;
+
+ if (div == NULL)
+ {
+ return ALT_E_BAD_ARG;
+ }
+
+ switch (clk)
+ {
+ // Main PLL outputs
+ case ALT_CLK_MAIN_PLL_C0:
+ case ALT_CLK_MPU:
+ *div = (ALT_CLKMGR_MAINPLL_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR)) + 1) *
+ (ALT_CLKMGR_ALTERA_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR)) + 1);
+ break;
+
+ case ALT_CLK_MAIN_PLL_C1:
+ case ALT_CLK_L4_MAIN:
+ case ALT_CLK_L3_MAIN:
+ *div = (ALT_CLKMGR_MAINPLL_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR)) + 1) *
+ (ALT_CLKMGR_ALTERA_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR)) + 1);
+ break;
+
+ case ALT_CLK_MAIN_PLL_C2:
+ case ALT_CLK_DBG_BASE:
+ case ALT_CLK_DBG_TIMER:
+ *div = (ALT_CLKMGR_MAINPLL_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR)) + 1) *
+ (ALT_CLKMGR_ALTERA_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_DBGATCLK_ADDR)) + 1);
+ break;
+
+ case ALT_CLK_MAIN_PLL_C3:
+ case ALT_CLK_MAIN_QSPI:
+ *div = (ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_MAIN_PLL_C4:
+ case ALT_CLK_MAIN_NAND_SDMMC:
+ *div = (ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_MAIN_PLL_C5:
+ case ALT_CLK_CFG:
+ case ALT_CLK_H2F_USER0:
+ *div = (ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR))) + 1;
+ break;
+
+ /////
+
+ // Peripheral PLL outputs
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ case ALT_CLK_EMAC0:
+ *div = (ALT_CLKMGR_PERPLL_EMAC0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ case ALT_CLK_EMAC1:
+ *div = (ALT_CLKMGR_PERPLL_EMAC1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ *div = (ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ *div = (ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ *div = (ALT_CLKMGR_PERPLL_PERBASECLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ case ALT_CLK_H2F_USER1:
+ *div = (ALT_CLKMGR_PERPLL_S2FUSER1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR))) + 1;
+ break;
+
+ /////
+
+ // SDRAM PLL outputs
+ case ALT_CLK_SDRAM_PLL_C0:
+ case ALT_CLK_DDR_DQS:
+ *div = (ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C1:
+ case ALT_CLK_DDR_2X_DQS:
+ *div = (ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C2:
+ case ALT_CLK_DDR_DQ:
+ *div = (ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR))) + 1;
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C5:
+ case ALT_CLK_H2F_USER2:
+ *div = (ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR))) + 1;
+ break;
+
+ /////
+
+ // Other clock dividers
+ case ALT_CLK_L3_MP:
+ temp = ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
+ if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_E_DIV2)
+ {
+ *div = temp + 1;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_L3_SP:
+ temp = ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
+ if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_E_DIV2)
+ {
+ *div = temp + 1;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ // note that this value does not include the additional effect
+ // of the L3_MP divider that is upchain from this one
+ break;
+
+ case ALT_CLK_L4_MP:
+ temp = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
+ if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV16)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_L4_SP:
+ temp = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
+ if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV16)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_DBG_AT:
+ temp = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR));
+ if (temp <= ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV4)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_DBG:
+ temp = ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR));
+ if (temp <= ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_E_DIV4)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ // note that this value does not include the value of the upstream dbg_at_clk divder
+ break;
+
+ case ALT_CLK_DBG_TRACE:
+ temp = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR));
+ if (temp <= ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV16)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_USB_MP:
+ temp = ALT_CLKMGR_PERPLL_DIV_USBCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
+ if (temp <= ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV16)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_SPI_M:
+ temp = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
+ if (temp <= ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV16)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_CAN0:
+ temp = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
+ if (temp <= ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV16)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_CAN1:
+ temp = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
+ if (temp <= ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV16)
+ {
+ *div = 1 << temp;
+ }
+ else
+ {
+ status = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_GPIO_DB:
+ temp = ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR));
+ *div = temp + 1;
+ break;
+
+ case ALT_CLK_MPU_PERIPH:
+ *div = 4; // set by hardware
+ break;
+
+ case ALT_CLK_MPU_L2_RAM:
+ *div = 2; // set by hardware
+ break;
+
+ case ALT_CLK_NAND:
+ *div = 4; // set by hardware
+ break;
+
+ default:
+ status = ALT_E_BAD_ARG;
+ break;
+ }
+
+ return status;
+}
+
+/////
+
+#define ALT_CLK_WITHIN_FREQ_LIMITS_TEST_MODE false
+ // used for testing writes to the the full range of counters without
+ // regard to the usual output frequency upper and lower limits
+
+
+static ALT_STATUS_CODE alt_clk_within_freq_limits(ALT_CLK_t clk, uint32_t div)
+{
+#if ALT_CLK_WITHIN_FREQ_LIMITS_TEST_MODE
+ return ALT_E_TRUE;
+#else
+
+ if (div == 0)
+ {
+ return ALT_E_BAD_ARG;
+ }
+
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+ uint32_t numer = 0;
+ uint32_t hilimit;
+ uint32_t lolimit;
+
+ switch (clk)
+ {
+ // Counters of the Main PLL
+ case ALT_CLK_MAIN_PLL_C0:
+ hilimit = alt_pll_cntr_maxfreq.MainPLL_C0;
+ lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
+ break;
+ case ALT_CLK_MAIN_PLL_C1:
+ hilimit = alt_pll_cntr_maxfreq.MainPLL_C1;
+ lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
+ break;
+ case ALT_CLK_MAIN_PLL_C2:
+ hilimit = alt_pll_cntr_maxfreq.MainPLL_C2;
+ lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
+ break;
+ case ALT_CLK_MAIN_PLL_C3:
+ hilimit = alt_pll_cntr_maxfreq.MainPLL_C3;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
+ break;
+ case ALT_CLK_MAIN_PLL_C4:
+ hilimit = alt_pll_cntr_maxfreq.MainPLL_C4;
+ lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
+ break;
+ case ALT_CLK_MAIN_PLL_C5:
+ hilimit = alt_pll_cntr_maxfreq.MainPLL_C5;
+ lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
+ break;
+
+ // Counters of the Peripheral PLL
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C0;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C1;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C2;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C3;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C4;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C5;
+ lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
+ break;
+
+ // Counters of the SDRAM PLL
+ case ALT_CLK_SDRAM_PLL_C0:
+ hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C0;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
+ break;
+ case ALT_CLK_SDRAM_PLL_C1:
+ hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C1;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
+ break;
+ case ALT_CLK_SDRAM_PLL_C2:
+ hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C2;
+ lolimit = 0;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
+ break;
+ case ALT_CLK_SDRAM_PLL_C5:
+ hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C5;
+ lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
+ status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
+ break;
+
+ default:
+ status = ALT_E_BAD_ARG;
+ break;
+ }
+
+ if (status == ALT_E_SUCCESS)
+ {
+ numer = numer / div;
+ if ((numer <= hilimit) && (numer >= lolimit))
+ {
+ status = ALT_E_TRUE;
+ }
+ else
+ {
+ status = ALT_E_FALSE;
+ }
+ }
+
+ return status;
+#endif
+}
+
+static bool alt_clkmgr_is_val_modulo_n(uint32_t div, uint32_t mod)
+{
+ if (mod == 1)
+ {
+ return true;
+ }
+ else if (mod == 2)
+ {
+ return (div & 0x1) == 0;
+ }
+ else if (mod == 4)
+ {
+ return (div & 0x3) == 0;
+ }
+ else
+ {
+ return (div % mod) == 0;
+ }
+}
+
+//
+// alt_clk_divider_set() sets the divider value for the specified clock.
+//
+// See pages 38, 44, 45, and 46 of the HPS-Clocking NPP for a map of the
+// HPS clocking architecture and hierarchy of connections.
+//
+ALT_STATUS_CODE alt_clk_divider_set(ALT_CLK_t clk, uint32_t div)
+{
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG;
+ volatile uint32_t temp, temp1;
+ uint32_t wrval = UINT32_MAX; // value to be written
+ bool restore_0 = false;
+ bool restore_1 = false;
+ bool restore_2 = false;
+
+ switch (clk)
+ {
+ // Main PLL outputs
+ case ALT_CLK_MAIN_PLL_C0:
+ case ALT_CLK_MPU:
+ {
+ uint32_t prediv = (ALT_CLKMGR_ALTERA_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR)) + 1);
+
+ if ( (div <= ((ALT_CLKMGR_MAINPLL_MPUCLK_CNT_SET_MSK + 1) * prediv))
+ && alt_clkmgr_is_val_modulo_n(div, prediv)
+ && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C0, div) == ALT_E_TRUE) )
+ {
+ wrval = (div / prediv) - 1;
+
+ // HW managed clock, change by writing to the external counter, no need to gate clock
+ // or match phase or wait for transistion time. No other field in the register to mask off either.
+ alt_write_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR, wrval);
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ }
+ break;
+
+ case ALT_CLK_MAIN_PLL_C1:
+ case ALT_CLK_L3_MAIN:
+ {
+ uint32_t prediv = (ALT_CLKMGR_ALTERA_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR)) + 1);
+
+ if ( (div <= ((ALT_CLKMGR_MAINPLL_MAINCLK_CNT_SET_MSK + 1) * prediv))
+ && alt_clkmgr_is_val_modulo_n(div, prediv)
+ && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C1, div) == ALT_E_TRUE) )
+ {
+ // HW managed clock, change by writing to the external counter, no need to gate clock
+ // or match phase or wait for transistion time. No other field in the register to mask off either.
+
+ wrval = (div / prediv) - 1;
+
+#if ALT_PREVENT_GLITCH_CHGC1
+ // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
+ // bypass state, then gate clock back on. FogBugz #63778
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
+ temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK)))
+ {
+ restore_0 = true;
+ }
+ if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK)))
+ {
+ restore_1 = true;
+ }
+ temp = temp1;
+ if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
+ if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
+
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR, wrval);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ // wait a bit before reenabling the L4MP and L4SP clocks
+ if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1); }
+#else
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR, wrval);
+#endif
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ }
+ break;
+
+ case ALT_CLK_MAIN_PLL_C2:
+ case ALT_CLK_DBG_BASE:
+ {
+ uint32_t prediv = (ALT_CLKMGR_ALTERA_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_DBGATCLK_ADDR)) + 1);
+
+ if ( (div <= ((ALT_CLKMGR_MAINPLL_DBGATCLK_CNT_SET_MSK + 1) * prediv))
+ && alt_clkmgr_is_val_modulo_n(div, prediv)
+ && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C2, div) == ALT_E_TRUE) )
+ {
+ wrval = (div / prediv) - 1;
+ // HW managed clock, change by writing to the external counter, no need to gate clock
+ // or match phase or wait for transistion time. No other field in the register to mask off either.
+ alt_write_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR, wrval);
+
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ }
+ break;
+
+ case ALT_CLK_MAIN_PLL_C3:
+ // The rest of the PLL outputs do not have external counters, but
+ // their internal counters are programmable rather than fixed
+ if ( (div <= (ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C3, div) == ALT_E_TRUE) )
+ {
+ // if the main_qspi_clk input is selected for the qspi_clk
+ if (ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR)) ==
+ ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
+ {
+ restore_0 = (temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)) & ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK;
+ if (restore_0) // AND if the QSPI clock is currently enabled
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_QSPICLK_CLR_MSK);
+ // gate off the QSPI clock
+ }
+
+ wrval = div - 1;
+ // the rest are software-managed clocks and require a reset sequence to write to
+ alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
+ ALT_CLKMGR_MAINPLL_STAT_ADDR,
+ ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C3,
+ ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ // if the QSPI clock was gated on (enabled) before, return it to that state
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_MAIN_PLL_C4:
+ case ALT_CLK_MAIN_NAND_SDMMC:
+ if ( (div <= (ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C4, div) == ALT_E_TRUE) )
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
+ temp1 = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+
+ // do we need to gate off the SDMMC clock ?
+ if (ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(temp) == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK)
+ {
+ if (temp1 & ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK) { restore_0 = true; }
+ }
+
+ // do we need to gate off the NAND clock and/or the NANDX clock?
+ if (ALT_CLKMGR_PERPLL_SRC_NAND_GET(temp) == ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK)
+ {
+ if (temp1 & ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK) { restore_1 = true; }
+ if (temp1 & ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK) { restore_2 = true; }
+ }
+
+ temp = temp1;
+ if (restore_1 && restore_2)
+ {
+ temp &= ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK;
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
+ // gate nand_clk off at least 8 MPU clock cycles before before nand_x_clk
+ }
+
+ if (restore_0 || restore_1)
+ {
+ if (restore_0) { temp &= ALT_CLKMGR_PERPLL_EN_SDMMCCLK_CLR_MSK; }
+ if (restore_1) { temp &= ALT_CLKMGR_PERPLL_EN_NANDXCLK_CLR_MSK; }
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ // gate off sdmmc_clk and/or nand_x_clk
+ }
+
+ // now write the new divisor ratio
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
+ ALT_CLKMGR_MAINPLL_STAT_ADDR,
+ ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C4,
+ ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+
+ if (restore_0 || restore_1)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1 & ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK);
+ // if the NANDX and/or SDMMC clock was gated on (enabled) before, return it to that state
+ if (restore_1 && restore_2)
+ {
+ // wait at least 8 clock cycles to turn the nand_clk on
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1);
+ }
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_MAIN_PLL_C5:
+ case ALT_CLK_CFG:
+ case ALT_CLK_H2F_USER0:
+ if ( (div <= (ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C5, div) == ALT_E_TRUE) )
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ restore_0 = ((temp & ALT_CLKMGR_MAINPLL_EN_CFGCLK_SET_MSK) ||
+ (temp & ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_SET_MSK));
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & (ALT_CLKMGR_MAINPLL_EN_CFGCLK_CLR_MSK &
+ ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_CLR_MSK)); // clear both
+ }
+
+ // now write the new divisor ratio
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
+ ALT_CLKMGR_MAINPLL_STAT_ADDR,
+ ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C5,
+ ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ /////
+
+ // Peripheral PLL outputs
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ case ALT_CLK_EMAC0:
+ if ( (div <= (ALT_CLKMGR_PERPLL_EMAC0CLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C0, div) == ALT_E_TRUE) )
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ restore_0 = temp & ALT_CLKMGR_PERPLL_EN_EMAC0CLK_SET_MSK;
+
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_EMAC0CLK_CLR_MSK);
+ }
+
+ // now write the new divisor ratio
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
+ ALT_CLKMGR_PERPLL_STAT_ADDR,
+ ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C0,
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ case ALT_CLK_EMAC1:
+ if ( (div <= (ALT_CLKMGR_PERPLL_EMAC1CLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C1, div) == ALT_E_TRUE) )
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ restore_0 = temp & ALT_CLKMGR_PERPLL_EN_EMAC1CLK_SET_MSK;
+
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_EMAC1CLK_CLR_MSK);
+ }
+ // now write the new divisor ratio
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
+ ALT_CLKMGR_PERPLL_STAT_ADDR,
+ ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C1,
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ if ( (div <= (ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C2, div) == ALT_E_TRUE) )
+ {
+ temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
+ {
+ // if qspi source is set to Peripheral PLL C2
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ // and if qspi_clk is enabled
+ restore_0 = temp & ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK;
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_QSPICLK_CLR_MSK);
+ // gate it off
+ }
+ }
+
+ // now write the new divisor ratio
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
+ ALT_CLKMGR_PERPLL_STAT_ADDR,
+ ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C2,
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ // if the clock was gated on (enabled) before, return it to that state
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ if ( (div <= (ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C3, div) == ALT_E_TRUE) )
+ {
+ // first, are the clock MUX input selections currently set to use the clock we want to change?
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
+ restore_0 = (ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(temp) == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK);
+ restore_1 = restore_2 = (ALT_CLKMGR_PERPLL_SRC_NAND_GET(temp) == ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK);
+
+ // now AND those with the current state of the three gate enables
+ // to get the clocks which must be gated off and then back on
+ temp1 = temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ restore_0 = restore_0 && (temp & ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK);
+ restore_1 = restore_1 && (temp & ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
+ restore_2 = restore_2 && (temp & ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
+
+ // gate off the clocks that depend on the clock divider that we want to change
+ if (restore_2) { temp &= ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK; }
+ if (restore_0) { temp &= ALT_CLKMGR_PERPLL_EN_SDMMCCLK_CLR_MSK; }
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+
+ // the NAND clock must be gated off before the NANDX clock,
+ if (restore_1)
+ {
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
+ temp &= ALT_CLKMGR_PERPLL_EN_NANDXCLK_CLR_MSK;
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+
+ // now write the new divisor ratio
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
+ ALT_CLKMGR_PERPLL_STAT_ADDR,
+ ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C3,
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
+
+ // NAND clock and NAND_X clock cannot be written together, must be a set sequence with a delay
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1 & ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK);
+ if (restore_2)
+ {
+ // the NANDX clock must be gated on before the NAND clock.
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK );
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ if ( (div <= (ALT_CLKMGR_PERPLL_PERBASECLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C4, div) == ALT_E_TRUE) )
+ {
+ // look at the L4 set of clock gates first
+ temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
+ restore_0 = (ALT_CLKMGR_MAINPLL_L4SRC_L4MP_GET(temp1) == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_PERIPHPLL);
+ restore_1 = (ALT_CLKMGR_MAINPLL_L4SRC_L4SP_GET(temp1) == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_PERIPHPLL);
+ temp1 = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ restore_0 = restore_0 && (temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK);
+ restore_1 = restore_1 && (temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK);
+
+ // if the l4_sp and l4_mp clocks are not set to use the periph_base_clk
+ // from the Peripheral PLL C4 clock divider output, or if they are
+ // not currently gated on, don't change their gates
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
+ if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
+
+ // now look at the C4 direct set of clock gates
+ // first, create a mask of the C4 direct set of clock gate enables
+ temp = ( ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK
+ | ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK
+ | ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK
+ | ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK
+ | ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK );
+
+ // gate off all the C4 Direct set of clocks
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1 & ~temp);
+
+ // change the clock divider ratio - the reason we're here
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
+ ALT_CLKMGR_PERPLL_STAT_ADDR,
+ ALT_CLKMGR_PERPLL_PERBASECLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C4,
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
+
+ // gate the affected clocks that were on before back on - both sets of gates
+ temp = (restore_0) ? ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK : 0;
+ if (restore_1) { temp |= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK; }
+ alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1);
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ case ALT_CLK_H2F_USER1:
+ if ( (div <= (ALT_CLKMGR_PERPLL_S2FUSER1CLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C5, div) == ALT_E_TRUE) )
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ restore_0 = temp & ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_SET_MSK;
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_CLR_MSK);
+ }
+
+ // now write the new divisor ratio
+ wrval = div - 1;
+ alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
+ ALT_CLKMGR_PERPLL_STAT_ADDR,
+ ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C5,
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
+ if (restore_0) { alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp); }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ /////
+
+ // SDRAM PLL outputs
+ case ALT_CLK_SDRAM_PLL_C0:
+ case ALT_CLK_DDR_DQS:
+ if ( (div <= (ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C0, div) == ALT_E_TRUE) )
+ {
+ wrval = div - 1;
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_CLR_MSK);
+ restore_0 = true;
+ }
+
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
+ ALT_CLKMGR_SDRPLL_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C0,
+ ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_LSB);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp); // which has the enable bit set
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C1:
+ case ALT_CLK_DDR_2X_DQS:
+ if ( (div <= (ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C1, div) == ALT_E_TRUE) )
+ {
+ wrval = div - 1;
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_CLR_MSK);
+ restore_0 = true;
+ }
+
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
+ ALT_CLKMGR_SDRPLL_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C1,
+ ALT_CLKMGR_SDRPLL_VCO_OUTRST_LSB);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp); // which has the enable bit set
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C2:
+ case ALT_CLK_DDR_DQ:
+ if ( (div <= (ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C2, div) == ALT_E_TRUE) )
+ {
+ wrval = div - 1;
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_CLR_MSK);
+ restore_0 = true;
+ }
+
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
+ ALT_CLKMGR_SDRPLL_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C2,
+ ALT_CLKMGR_SDRPLL_VCO_OUTRST_LSB);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp); // which has the enable bit set
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C5:
+ case ALT_CLK_H2F_USER2:
+ if ( (div <= (ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_SET_MSK + 1))
+ && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C5, div) == ALT_E_TRUE) )
+ {
+ wrval = div - 1;
+ temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_CLR_MSK);
+ restore_0 = true;
+ }
+
+ alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
+ ALT_CLKMGR_SDRPLL_STAT_ADDR,
+ ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C5,
+ ALT_CLKMGR_SDRPLL_VCO_OUTRST_LSB);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp); // which has the enable bit set
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ /////
+
+ // Other clock dividers
+ case ALT_CLK_L3_MP:
+ if (div == 1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_E_DIV2; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_MAINPLL_EN_L3MPCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_L3MPCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_SET_MSK,
+ wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); // which has the enable bit set
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_L3_SP:
+ // note that the L3MP divider is upstream from the L3SP divider
+ // and any changes to the former will affect the output of both
+ if (div == 1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_E_DIV2; }
+
+ if (wrval != UINT32_MAX)
+ {
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_SET_MSK,
+ wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_LSB);
+ // no clock gate to close and reopen
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_L4_MP:
+ if (div == 1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV4; }
+ else if (div == 8) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV8; }
+ else if (div == 16) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV16; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_SET_MSK,
+ wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); // which has the enable bit set
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_L4_SP:
+ if (div == 1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV4; }
+ else if (div == 8) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV8; }
+ else if (div == 16) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV16; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_SET_MSK,
+ wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_DBG_AT:
+ if (div == 1) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV4; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_MAINPLL_EN_DBGATCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_DBGATCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_SET_MSK,
+ wrval << ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_DBG:
+ if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_E_DIV4; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_MAINPLL_EN_DBGCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_DBGCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_SET_MSK,
+ wrval << (ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_LSB - 1));
+ // account for the fact that the divisor ratios are 2x the value
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_DBG_TRACE:
+ if (div == 1) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV4; }
+ else if (div == 8) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV8; }
+ else if (div == 16) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV16; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR, ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_SET_MSK,
+ wrval << ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_USB_MP:
+ if (div == 1) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV4; }
+ else if (div == 8) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV8; }
+ else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV16; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_USBCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_USBCLK_SET_MSK,
+ wrval << ALT_CLKMGR_PERPLL_DIV_USBCLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_SPI_M:
+ if (div == 1) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV4; }
+ else if (div == 8) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV8; }
+ else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV16; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_SPIMCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_SPIMCLK_SET_MSK,
+ wrval << ALT_CLKMGR_PERPLL_DIV_SPIMCLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_CAN0:
+ if (div == 1) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV4; }
+ else if (div == 8) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV8; }
+ else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV16; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_CAN0CLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_CAN0CLK_SET_MSK,
+ wrval << ALT_CLKMGR_PERPLL_DIV_CAN0CLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_CAN1:
+ if (div == 1) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV1; }
+ else if (div == 2) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV2; }
+ else if (div == 4) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV4; }
+ else if (div == 8) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV8; }
+ else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV16; }
+
+ if (wrval != UINT32_MAX)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_CAN1CLK_CLR_MSK);
+ restore_0 = true;
+ }
+ alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_CAN1CLK_SET_MSK,
+ wrval << ALT_CLKMGR_PERPLL_DIV_CAN1CLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_GPIO_DB: // GPIO debounce clock
+ if (div <= ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET_MSK)
+ {
+ temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+ if (temp & ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK)
+ {
+ // if clock is currently on, gate it off
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_GPIOCLK_CLR_MSK);
+ restore_0 = true;
+ }
+ wrval = div - 1;
+ alt_replbits_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR, ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET_MSK,
+ wrval << ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_LSB);
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_GPIODIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ break;
+
+ case ALT_CLK_MAIN_QSPI:
+ temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ // get the QSPI clock source
+ restore_0 = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR) & ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK;
+ // and the current enable state
+ wrval = div - 1;
+
+ if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
+ { // if the main_qspi_clk (Main PLL C3 Ouput) input is selected
+ if (div <= ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_SET_MSK)
+ {
+ if (restore_0)
+ {
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
+ } // gate off the QSPI clock
+
+ alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
+ ALT_CLKMGR_MAINPLL_STAT_ADDR,
+ ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C3,
+ ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
+ // if the QSPI clock was gated on (enabled) before, return it to that state
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
+ {
+ if (div <= ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_SET_MSK)
+ {
+ if (restore_0)
+ {
+ alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
+ } // gate off the QSPI clock
+
+ alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
+ ALT_CLKMGR_PERPLL_STAT_ADDR,
+ ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR,
+ wrval,
+ ALT_CLK_PLL_RST_BIT_C2,
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
+
+ alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
+ if (restore_0)
+ {
+ alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
+ // if the QSPI clock was gated on (enabled) before, return it to that state
+ }
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ARG_RANGE;
+ }
+ }
+ break;
+
+ /////
+
+ default:
+ ret = ALT_E_BAD_ARG;
+ break;
+ }
+
+ return ret;
+}
+
+//
+// alt_clk_freq_get() returns the output frequency of the specified clock.
+//
+ALT_STATUS_CODE alt_clk_freq_get(ALT_CLK_t clk, alt_freq_t* freq)
+{
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG;
+ uint32_t temp = 0;
+ uint64_t numer = 0;
+ uint64_t denom = 1;
+
+ if (freq == NULL)
+ {
+ return ret;
+ }
+
+ switch (clk)
+ {
+ // External Inputs
+ case ALT_CLK_IN_PIN_OSC1:
+ case ALT_CLK_OSC1:
+ numer = alt_ext_clk_paramblok.clkosc1.freqcur;
+ // denom = 1 by default
+ ret = ALT_E_SUCCESS;
+ break;
+
+ case ALT_CLK_IN_PIN_OSC2:
+ numer = alt_ext_clk_paramblok.clkosc2.freqcur;
+ // denom = 1 by default
+ ret = ALT_E_SUCCESS;
+ break;
+
+ case ALT_CLK_F2H_PERIPH_REF:
+ numer = alt_ext_clk_paramblok.periph.freqcur;
+ // denom = 1 by default
+ ret = ALT_E_SUCCESS;
+ break;
+
+ case ALT_CLK_F2H_SDRAM_REF:
+ numer = alt_ext_clk_paramblok.sdram.freqcur;
+ // denom = 1 by default
+ ret = ALT_E_SUCCESS;
+ break;
+
+ /////
+
+ // PLLs
+ case ALT_CLK_MAIN_PLL:
+ if (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE)
+ {
+ temp = alt_ext_clk_paramblok.clkosc1.freqcur;
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ }
+ numer = (uint64_t) temp;
+ // denom = 1 by default
+ break;
+
+ case ALT_CLK_PERIPHERAL_PLL:
+ if (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE)
+ {
+ temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
+ {
+ temp = alt_ext_clk_paramblok.clkosc1.freqcur;
+ ret = ALT_E_SUCCESS;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
+ {
+ temp = alt_ext_clk_paramblok.clkosc2.freqcur;
+ ret = ALT_E_SUCCESS;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
+ {
+ temp = alt_ext_clk_paramblok.periph.freqcur;
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ }
+ else
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ }
+ numer = (uint64_t) temp;
+ // denom = 1 by default
+ break;
+
+ case ALT_CLK_SDRAM_PLL:
+ if (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE)
+ {
+ temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
+ if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
+ {
+ temp = alt_ext_clk_paramblok.clkosc1.freqcur;
+ ret = ALT_E_SUCCESS;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
+ {
+ temp = alt_ext_clk_paramblok.clkosc2.freqcur;
+ ret = ALT_E_SUCCESS;
+ }
+ else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
+ {
+ temp = alt_ext_clk_paramblok.sdram.freqcur;
+ ret = ALT_E_SUCCESS;
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ }
+ else
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
+ }
+ numer = (uint64_t) temp;
+ // denom = 1 by default
+ break;
+
+ /////
+
+ // Main Clock Group
+ case ALT_CLK_MAIN_PLL_C0:
+ case ALT_CLK_MAIN_PLL_C1:
+ case ALT_CLK_MAIN_PLL_C2:
+ case ALT_CLK_MAIN_PLL_C3:
+ case ALT_CLK_MAIN_PLL_C4:
+ case ALT_CLK_MAIN_PLL_C5:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(clk, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_MPU:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C0, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_MPU_PERIPH:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C0, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MPU_PERIPH, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_MPU_L2_RAM:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C0, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MPU_L2_RAM, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_L4_MAIN:
+ case ALT_CLK_L3_MAIN:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_L3_MP:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_L3_MP, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_L3_SP:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_L3_MP, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = denom * (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_L3_SP, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_L4_MP:
+ ret = alt_clk_divider_get(ALT_CLK_L4_MP, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ temp = ALT_CLKMGR_MAINPLL_L4SRC_L4MP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR));
+ if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_MAINPLL)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
+ denom = denom * (uint64_t) temp; // no real harm if temp is garbage data
+ }
+ }
+ else if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_PERIPHPLL)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ }
+ }
+ break;
+
+ case ALT_CLK_L4_SP:
+ ret = alt_clk_divider_get(ALT_CLK_L4_SP, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ temp = ALT_CLKMGR_MAINPLL_L4SRC_L4SP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR));
+ if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_MAINPLL)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ }
+ else if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_PERIPHPLL) // periph_base_clk
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ }
+ }
+ break;
+
+ case ALT_CLK_DBG_BASE:
+ case ALT_CLK_DBG_TIMER:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_DBG_AT:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_DBG_AT, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_DBG:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_DBG_AT, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = denom * (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_DBG, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_DBG_TRACE:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_DBG_TRACE, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_MAIN_QSPI:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C3, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_MAIN_NAND_SDMMC:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C4, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_CFG:
+ case ALT_CLK_H2F_USER0:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C5, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ /////
+
+ // Peripheral Clock Group
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(clk, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_EMAC0:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C0, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_EMAC1:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C1, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_USB_MP:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_USB_MP, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ }
+ break;
+
+ case ALT_CLK_SPI_M:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_SPI_M, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_CAN0:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_CAN0, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_CAN1:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_CAN1, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_GPIO_DB:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
+ }
+ if (ret == ALT_E_SUCCESS)
+ {
+ denom = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_GPIO_DB, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_H2F_USER1:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C5, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ /* Clocks That Can Switch Between Different Clock Groups */
+ case ALT_CLK_SDMMC:
+ temp = ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_F2S_PERIPH_REF_CLK)
+ {
+ numer = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
+ // denom = 1 by default
+ ret = ALT_E_SUCCESS;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C4, &temp);
+ denom = (uint64_t) temp;
+ }
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C3, &temp);
+ denom = (uint64_t) temp;
+ }
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_NAND:
+ denom = 4;
+ // the absence of a break statement here is not a mistake
+ case ALT_CLK_NAND_X:
+ temp = ALT_CLKMGR_PERPLL_SRC_NAND_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_F2S_PERIPH_REF_CLK)
+ {
+ numer = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
+ // denom = 1 or 4 by default;
+ ret = ALT_E_SUCCESS;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C4, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C3, &temp);
+ denom = denom * (uint64_t) temp;
+ }
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ break;
+
+ case ALT_CLK_QSPI:
+ temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
+ if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_F2S_PERIPH_REF_CLK)
+ {
+ numer = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
+ // denom = 1 by default;
+ ret = ALT_E_SUCCESS;
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C3, &temp);
+ denom = (uint64_t) temp;
+ }
+ }
+ else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
+ {
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C2, &temp);
+ denom = (uint64_t) temp;
+ }
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ break;
+
+ /////
+
+ // SDRAM Clock Group
+ case ALT_CLK_SDRAM_PLL_C0:
+ case ALT_CLK_DDR_DQS:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C0, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C1:
+ case ALT_CLK_DDR_2X_DQS:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C1, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C2:
+ case ALT_CLK_DDR_DQ:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C2, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ case ALT_CLK_SDRAM_PLL_C5:
+ case ALT_CLK_H2F_USER2:
+ ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
+ if (ret == ALT_E_SUCCESS)
+ {
+ numer = (uint64_t) temp;
+ ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C5, &temp);
+ denom = (uint64_t) temp;
+ }
+ break;
+
+ default:
+ ret = ALT_E_BAD_ARG;
+ break;
+
+ } // end of switch-case construct
+
+ if (ret == ALT_E_SUCCESS)
+ {
+ // will not get here if none of above cases match
+ if (denom > 0)
+ {
+ numer /= denom;
+ if (numer <= UINT32_MAX)
+ {
+ *freq = (uint32_t) numer;
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ }
+ else
+ {
+ ret = ALT_E_ERROR;
+ }
+ }
+
+ return ret;
+}
+
+//
+// alt_clk_irq_disable() disables one or more of the lock status conditions as
+// contributors to the clkmgr_IRQ interrupt signal state.
+//
+ALT_STATUS_CODE alt_clk_irq_disable(ALT_CLK_PLL_LOCK_STATUS_t lock_stat_mask)
+{
+ if (!(lock_stat_mask & ALT_CLK_MGR_PLL_LOCK_BITS))
+ {
+ alt_clrbits_word(ALT_CLKMGR_INTREN_ADDR, lock_stat_mask);
+ return ALT_E_SUCCESS;
+ }
+ else
+ {
+ return ALT_E_BAD_ARG;
+ }
+}
+
+//
+// alt_clk_irq_enable() enables one or more of the lock status conditions as
+// contributors to the clkmgr_IRQ interrupt signal state.
+//
+ALT_STATUS_CODE alt_clk_irq_enable(ALT_CLK_PLL_LOCK_STATUS_t lock_stat_mask)
+{
+ if (!(lock_stat_mask & ALT_CLK_MGR_PLL_LOCK_BITS))
+ {
+ alt_setbits_word(ALT_CLKMGR_INTREN_ADDR, lock_stat_mask);
+ return ALT_E_SUCCESS;
+ }
+ else
+ {
+ return ALT_E_BAD_ARG;
+ }
+}
+
+/////
+
+//
+// alt_clk_group_cfg_raw_get() gets the raw configuration state of the designated
+// clock group.
+//
+ALT_STATUS_CODE alt_clk_group_cfg_raw_get(ALT_CLK_GRP_t clk_group,
+ ALT_CLK_GROUP_RAW_CFG_t * clk_group_raw_cfg)
+{
+ clk_group_raw_cfg->verid = alt_read_word(ALT_SYSMGR_SILICONID1_ADDR);
+ clk_group_raw_cfg->siliid2 = alt_read_word(ALT_SYSMGR_SILICONID2_ADDR);
+ clk_group_raw_cfg->clkgrpsel = clk_group;
+
+ if (clk_group == ALT_MAIN_PLL_CLK_GRP)
+ {
+ // Main PLL VCO register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.vco = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
+
+ // Main PLL Misc register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.misc = alt_read_word(ALT_CLKMGR_MAINPLL_MISC_ADDR);
+
+ // Main PLL C0-C5 Counter registers
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mpuclk = alt_read_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR);
+ // doing these as 32-bit reads and writes avoids unnecessary masking operations
+
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainclk = alt_read_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR);
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgatclk = alt_read_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR);
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainqspiclk = alt_read_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR);
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainnandsdmmcclk = alt_read_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR);
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.cfgs2fuser0clk = alt_read_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR);
+
+ // Main PLL Enable register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.en = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
+
+ // Main PLL Maindiv register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.maindiv = alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR);
+
+ // Main PLL Debugdiv register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgdiv = alt_read_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR);
+
+ // Main PLL Tracediv register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.tracediv = alt_read_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR);
+
+ // Main PLL L4 Source register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.l4src = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
+
+ // Main PLL Status register
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw.stat = alt_read_word(ALT_CLKMGR_MAINPLL_STAT_ADDR);
+ // clkgrp.mainpllgrp.stat.outresetack is defined in the ALT_CLKMGR_MAINPLL_STAT_s declaration
+ // as a const but alt_indwrite_word() overrides that restriction.
+
+ // padding ...
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw._pad_0x38_0x40[0] = 0;
+ clk_group_raw_cfg->clkgrp.mainpllgrp.raw._pad_0x38_0x40[1] = 0;
+
+ return ALT_E_SUCCESS;
+ }
+ else if (clk_group == ALT_PERIPH_PLL_CLK_GRP)
+ {
+ // Peripheral PLL VCO register
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.vco = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
+
+ // Peripheral PLL Misc register
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.misc = alt_read_word(ALT_CLKMGR_PERPLL_MISC_ADDR);
+
+ // Peripheral PLL C0-C5 Counters
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac0clk = alt_read_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR);
+ // doing these as 32-bit reads and writes avoids unnecessary masking operations
+
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac1clk = alt_read_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR);
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.perqspiclk = alt_read_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR);
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.pernandsdmmcclk = alt_read_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR);
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.perbaseclk = alt_read_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR);
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.s2fuser1clk = alt_read_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR);
+
+ // Peripheral PLL Enable register
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.en = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
+
+ // Peripheral PLL Divider register
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.div = alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR);
+
+ // Peripheral PLL GPIO Divider register
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.gpiodiv = alt_read_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR);
+
+ // Peripheral PLL Source register
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.src = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
+
+ // Peripheral PLL Status register
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw.stat = alt_read_word(ALT_CLKMGR_PERPLL_STAT_ADDR);
+
+ // padding ...
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw._pad_0x34_0x40[0] = 0;
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw._pad_0x34_0x40[1] = 0;
+ clk_group_raw_cfg->clkgrp.perpllgrp.raw._pad_0x34_0x40[2] = 0;
+
+ return ALT_E_SUCCESS;
+ }
+ else if (clk_group == ALT_SDRAM_PLL_CLK_GRP)
+ {
+ // SDRAM PLL VCO register
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.vco = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
+
+ // SDRAM PLL Control register
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ctrl = alt_read_word(ALT_CLKMGR_SDRPLL_CTL_ADDR);
+
+ // SDRAM PLL C0-C2 & C5 Counters
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqsclk = alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR);
+ // doing these as 32-bit reads and writes avoids unnecessary masking operations
+
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddr2xdqsclk = alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR);
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqclk = alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR);
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.s2fuser2clk = alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR);
+
+ // SDRAM PLL Enable register
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.en = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
+
+ // SDRAM PLL Status register
+ clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.stat = alt_read_word(ALT_CLKMGR_SDRPLL_STAT_ADDR);
+
+ return ALT_E_SUCCESS;
+ }
+ else
+ {
+ return ALT_E_BAD_ARG;
+ }
+}
+
+//
+// alt_clk_group_cfg_raw_set() sets the clock group configuration.
+//
+ALT_STATUS_CODE alt_clk_group_cfg_raw_set(const ALT_CLK_GROUP_RAW_CFG_t * clk_group_raw_cfg)
+{
+ // test for matching silicon ID, but not for matching silicon revision number
+ if (ALT_SYSMGR_SILICONID1_ID_GET(alt_read_word(ALT_SYSMGR_SILICONID1_ADDR)) !=
+ ALT_SYSMGR_SILICONID1_ID_GET(clk_group_raw_cfg->verid))
+ {
+ return ALT_E_BAD_VERSION;
+ }
+
+ // get the PLL ID
+ ALT_CLK_GRP_t clk_group = clk_group_raw_cfg->clkgrpsel;
+ ALT_CLK_t pll;
+
+ if (clk_group == ALT_MAIN_PLL_CLK_GRP) { pll = ALT_CLK_MAIN_PLL; }
+ else if (clk_group == ALT_PERIPH_PLL_CLK_GRP) { pll = ALT_CLK_PERIPHERAL_PLL; }
+ else if (clk_group == ALT_SDRAM_PLL_CLK_GRP) { pll = ALT_CLK_SDRAM_PLL; }
+ else
+ {
+ return ALT_E_ERROR;
+ }
+
+ ALT_STATUS_CODE status = ALT_E_SUCCESS;
+
+ // if the PLL isn't in bypass mode, put it in bypass mode
+ bool byp = false;
+ if (alt_clk_pll_is_bypassed(pll) == ALT_E_FALSE)
+ {
+ status = alt_clk_pll_bypass_enable(pll, false);
+ if (status != ALT_E_SUCCESS)
+ {
+ return status;
+ }
+
+ byp = true;
+ }
+
+ // now write the values in the ALT_CLK_GROUP_RAW_CFG_t structure to the registers
+ if (clk_group == ALT_MAIN_PLL_CLK_GRP)
+ {
+ // Main PLL VCO register
+ alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.vco &
+ ALT_CLKMGR_MAINPLL_VCO_OUTRSTALL_CLR_MSK & ALT_CLKMGR_MAINPLL_VCO_OUTRST_CLR_MSK);
+ // the outreset and outresetall bits were probably clear when the
+ // state was saved, but make sure they're clear now
+
+ // Main PLL Misc register
+ alt_write_word(ALT_CLKMGR_MAINPLL_MISC_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.misc);
+
+ // Main PLL C0-C5 Counter registers
+ alt_write_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mpuclk);
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainclk);
+ alt_write_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgatclk);
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainqspiclk);
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainnandsdmmcclk);
+ alt_write_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.cfgs2fuser0clk);
+
+ // Main PLL Counter Enable register
+ alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.en);
+
+ // Main PLL Maindiv register
+ alt_write_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.maindiv);
+
+ // Main PLL Debugdiv register
+ alt_write_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgdiv);
+
+ // Main PLL Tracediv register
+ alt_write_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.tracediv);
+
+ // Main PLL L4 Source register
+ alt_write_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.l4src);
+ }
+ else if (clk_group == ALT_PERIPH_PLL_CLK_GRP)
+ {
+ // Peripheral PLL VCO register
+ alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.vco &
+ ALT_CLKMGR_PERPLL_VCO_OUTRST_CLR_MSK & ALT_CLKMGR_PERPLL_VCO_OUTRSTALL_CLR_MSK);
+ // the outreset and outresetall bits were probably clear when the
+ // state was saved, but make sure they're clear now
+
+ // Peripheral PLL Misc register
+ alt_write_word(ALT_CLKMGR_PERPLL_MISC_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.misc);
+
+ // Peripheral PLL C0-C5 Counters
+ alt_write_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac0clk);
+ alt_write_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac1clk);
+ alt_write_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.perqspiclk);
+ alt_write_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.pernandsdmmcclk);
+ alt_write_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.perbaseclk);
+ alt_write_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.s2fuser1clk);
+
+ // Peripheral PLL Counter Enable register
+ alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.en);
+
+ // Peripheral PLL Divider register
+ alt_write_word(ALT_CLKMGR_PERPLL_DIV_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.div);
+
+ // Peripheral PLL GPIO Divider register
+ alt_write_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.gpiodiv);
+
+ // Peripheral PLL Source register
+ alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.src);
+ }
+ else if (clk_group == ALT_SDRAM_PLL_CLK_GRP)
+ {
+ // SDRAM PLL VCO register
+ alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.vco &
+ ALT_CLKMGR_SDRPLL_VCO_OUTRST_CLR_MSK & ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_CLR_MSK);
+ // the outreset and outresetall bits were probably clear when the
+ // state was saved, but make sure they're clear now
+
+ // SDRAM PLL Control register
+ alt_write_word(ALT_CLKMGR_SDRPLL_CTL_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ctrl);
+
+ // SDRAM PLL C0-C2 & C5 Counters
+ alt_write_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqsclk);
+ alt_write_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddr2xdqsclk);
+ alt_write_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqclk);
+ alt_write_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.s2fuser2clk);
+
+ // SDRAM PLL Counter Enable register
+ alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.en);
+ }
+
+ // if PLL was not bypassed before, restore that state
+ if (byp)
+ {
+ status = alt_clk_pll_bypass_disable(pll);
+ }
+
+ return status;
+}
+
+//
+// alt_clk_id_to_string() converts a clock ID to a text string.
+//
+ALT_STATUS_CODE alt_clk_id_to_string(ALT_CLK_t clk_id, char * output, size_t size)
+{
+ char * name = NULL;
+
+ switch (clk_id)
+ {
+ case ALT_CLK_IN_PIN_OSC1:
+ name = "IN_PIN_OSC1";
+ break;
+ case ALT_CLK_IN_PIN_OSC2:
+ name = "IN_PIN_OSC2";
+ break;
+
+ // FPGA Clock Sources External to HPS
+ case ALT_CLK_F2H_PERIPH_REF:
+ name = "F2H_PERIPH_REF";
+ break;
+ case ALT_CLK_F2H_SDRAM_REF:
+ name = "F2H_SDRAM_REF";
+ break;
+
+ // Other Clock Sources External to HPS
+ case ALT_CLK_IN_PIN_JTAG:
+ name = "IN_PIN_JTAG";
+ break;
+ case ALT_CLK_IN_PIN_ULPI0:
+ name = "IN_PIN_ULPI0";
+ break;
+ case ALT_CLK_IN_PIN_ULPI1:
+ name = "IN_PIN_ULPI1";
+ break;
+ case ALT_CLK_IN_PIN_EMAC0_RX:
+ name = "IN_PIN_EMAC0_RX";
+ break;
+ case ALT_CLK_IN_PIN_EMAC1_RX:
+ name = "IN_PIN_EMAC1_RX";
+ break;
+
+ // PLLs
+ case ALT_CLK_MAIN_PLL:
+ name = "MAIN_PLL";
+ break;
+ case ALT_CLK_PERIPHERAL_PLL:
+ name = "PERIPHERAL_PLL";
+ break;
+ case ALT_CLK_SDRAM_PLL:
+ name = "SDRAM_PLL";
+ break;
+
+ // OSC1 Clock Group - The OSC1 clock group contains those clocks which are derived
+ // directly from the osc_clk_1_HPS pin
+ case ALT_CLK_OSC1:
+ name = "OSC1";
+ break;
+
+ // Main Clock Group - The following clocks are derived from the Main PLL.
+ case ALT_CLK_MAIN_PLL_C0:
+ name = "MAIN_PLL_C0";
+ break;
+ case ALT_CLK_MAIN_PLL_C1:
+ name = "MAIN_PLL_C1";
+ break;
+ case ALT_CLK_MAIN_PLL_C2:
+ name = "MAIN_PLL_C2";
+ break;
+ case ALT_CLK_MAIN_PLL_C3:
+ name = "MAIN_PLL_C3";
+ break;
+ case ALT_CLK_MAIN_PLL_C4:
+ name = "MAIN_PLL_C4";
+ break;
+ case ALT_CLK_MAIN_PLL_C5:
+ name = "MAIN_PLL_C5";
+ break;
+ case ALT_CLK_MPU:
+ name = "MPU";
+ break;
+ case ALT_CLK_MPU_L2_RAM:
+ name = "MPU_L2_RAM";
+ break;
+ case ALT_CLK_MPU_PERIPH:
+ name = "MPU_PERIPH";
+ break;
+ case ALT_CLK_L3_MAIN:
+ name = "L3_MAIN";
+ break;
+ case ALT_CLK_L3_MP:
+ name = "L3_MP";
+ break;
+ case ALT_CLK_L3_SP:
+ name = "L3_SP";
+ break;
+ case ALT_CLK_L4_MAIN:
+ name = "L4_MAIN";
+ break;
+ case ALT_CLK_L4_MP:
+ name = "L4_MP";
+ break;
+ case ALT_CLK_L4_SP:
+ name = "L4_SP";
+ break;
+ case ALT_CLK_DBG_BASE:
+ name = "DBG_BASE";
+ break;
+ case ALT_CLK_DBG_AT:
+ name = "DBG_AT";
+ break;
+ case ALT_CLK_DBG_TRACE:
+ name = "DBG_TRACE";
+ break;
+ case ALT_CLK_DBG_TIMER:
+ name = "DBG_TIMER";
+ break;
+ case ALT_CLK_DBG:
+ name = "DBG";
+ break;
+ case ALT_CLK_MAIN_QSPI:
+ name = "MAIN_QSPI";
+ break;
+ case ALT_CLK_MAIN_NAND_SDMMC:
+ name = "MAIN_NAND_SDMMC";
+ break;
+ case ALT_CLK_CFG:
+ name = "CFG";
+ break;
+ case ALT_CLK_H2F_USER0:
+ name = "H2F_USER0";
+ break;
+
+ // Peripherals Clock Group - The following clocks are derived from the Peripheral PLL.
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ name = "PERIPHERAL_PLL_C0";
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ name = "PERIPHERAL_PLL_C1";
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ name = "PERIPHERAL_PLL_C2";
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ name = "PERIPHERAL_PLL_C3";
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ name = "PERIPHERAL_PLL_C4";
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ name = "PERIPHERAL_PLL_C5";
+ break;
+ case ALT_CLK_USB_MP:
+ name = "USB_MP";
+ break;
+ case ALT_CLK_SPI_M:
+ name = "SPI_M";
+ break;
+ case ALT_CLK_QSPI:
+ name = "QSPI";
+ break;
+ case ALT_CLK_NAND_X:
+ name = "NAND_X";
+ break;
+ case ALT_CLK_NAND:
+ name = "NAND";
+ break;
+ case ALT_CLK_SDMMC:
+ name = "SDMMC";
+ break;
+ case ALT_CLK_EMAC0:
+ name = "EMAC0";
+ break;
+ case ALT_CLK_EMAC1:
+ name = "EMAC1";
+ break;
+ case ALT_CLK_CAN0:
+ name = "CAN0";
+ break;
+ case ALT_CLK_CAN1:
+ name = "CAN1";
+ break;
+ case ALT_CLK_GPIO_DB:
+ name = "GPIO_DB";
+ break;
+ case ALT_CLK_H2F_USER1:
+ name = "H2F_USER1";
+ break;
+
+ // SDRAM Clock Group - The following clocks are derived from the SDRAM PLL.
+ case ALT_CLK_SDRAM_PLL_C0:
+ name = "SDRAM_PLL_C0";
+ break;
+ case ALT_CLK_SDRAM_PLL_C1:
+ name = "SDRAM_PLL_C1";
+ break;
+ case ALT_CLK_SDRAM_PLL_C2:
+ name = "SDRAM_PLL_C2";
+ break;
+ case ALT_CLK_SDRAM_PLL_C3:
+ name = "SDRAM_PLL_C3";
+ break;
+ case ALT_CLK_SDRAM_PLL_C4:
+ name = "SDRAM_PLL_C4";
+ break;
+ case ALT_CLK_SDRAM_PLL_C5:
+ name = "SDRAM_PLL_C5";
+ break;
+ case ALT_CLK_DDR_DQS:
+ name = "DDR_DQS";
+ break;
+ case ALT_CLK_DDR_2X_DQS:
+ name = "DDR_2X_DQS";
+ break;
+ case ALT_CLK_DDR_DQ:
+ name = "DDR_DQ";
+ break;
+ case ALT_CLK_H2F_USER2:
+ name = "H2F_USER2";
+ break;
+
+ // Clock Output Pins
+ case ALT_CLK_OUT_PIN_EMAC0_TX:
+ name = "OUT_PIN_EMAC0_TX";
+ break;
+ case ALT_CLK_OUT_PIN_EMAC1_TX:
+ name = "OUT_PIN_EMAC1_TX";
+ break;
+ case ALT_CLK_OUT_PIN_SDMMC:
+ name = "OUT_PIN_SDMMC";
+ break;
+ case ALT_CLK_OUT_PIN_I2C0_SCL:
+ name = "OUT_PIN_I2C0_SCL";
+ break;
+ case ALT_CLK_OUT_PIN_I2C1_SCL:
+ name = "OUT_PIN_I2C1_SCL";
+ break;
+ case ALT_CLK_OUT_PIN_I2C2_SCL:
+ name = "OUT_PIN_I2C2_SCL";
+ break;
+ case ALT_CLK_OUT_PIN_I2C3_SCL:
+ name = "OUT_PIN_I2C3_SCL";
+ break;
+ case ALT_CLK_OUT_PIN_SPIM0:
+ name = "OUT_PIN_SPIM0";
+ break;
+ case ALT_CLK_OUT_PIN_SPIM1:
+ name = "OUT_PIN_SPIM1";
+ break;
+ case ALT_CLK_OUT_PIN_QSPI:
+ name = "OUT_PIN_QSPI";
+ break;
+ case ALT_CLK_UNKNOWN:
+ name = "UNKNOWN";
+ break;
+
+ // do *not* put a 'default' statement here. Then the compiler will throw
+ // an error if another clock id enum is added if the corresponding
+ // string is not added to this function.
+ }
+
+ if (name != NULL)
+ {
+ snprintf(output, size, "ALT_CLK_%s", name);
+ return ALT_E_SUCCESS;
+ }
+ else
+ {
+ return ALT_E_BAD_ARG;
+ }
+}
+
+
+//
+// alt_clk_pll_cntr_maxfreq_recalc() recalculate the maxmum frequency of the specified clock.
+//
+ALT_STATUS_CODE alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_t clk, ALT_PLL_CNTR_FREQMAX_t * maxfreq)
+{
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG;
+ alt_freq_t freq;
+
+ ret = alt_clk_freq_get(clk, &freq);
+
+ if (ret == ALT_E_SUCCESS)
+ {
+
+ switch (clk)
+ {
+ // Main Clock Group
+ case ALT_CLK_MAIN_PLL_C0:
+ maxfreq->MainPLL_C0 = freq;
+ printf("alt_pll_cntr_maxfreq.MainPLL_C0 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_MAIN_PLL_C1:
+ maxfreq->MainPLL_C1 = freq;
+ printf("alt_pll_cntr_maxfreq.MainPLL_C1 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_MAIN_PLL_C2:
+ maxfreq->MainPLL_C2 = freq;
+ printf("alt_pll_cntr_maxfreq.MainPLL_C2 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_MAIN_PLL_C3:
+ maxfreq->MainPLL_C3 = freq;
+ printf("alt_pll_cntr_maxfreq.MainPLL_C3 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_MAIN_PLL_C4:
+ maxfreq->MainPLL_C4 = freq;
+ printf("alt_pll_cntr_maxfreq.MainPLL_C4 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_MAIN_PLL_C5:
+ maxfreq->MainPLL_C5 = freq;
+ printf("alt_pll_cntr_maxfreq.MainPLL_C5 = %10d\n", (unsigned int)freq);
+ break;
+
+ // Peripheral Clock Group
+ case ALT_CLK_PERIPHERAL_PLL_C0:
+ maxfreq->PeriphPLL_C0 = freq;
+ printf("alt_pll_cntr_maxfreq.PeriphPLL_C0 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C1:
+ maxfreq->PeriphPLL_C1 = freq;
+ printf("alt_pll_cntr_maxfreq.PeriphPLL_C1 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C2:
+ maxfreq->PeriphPLL_C2 = freq;
+ printf("alt_pll_cntr_maxfreq.PeriphPLL_C2 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C3:
+ maxfreq->PeriphPLL_C3 = freq;
+ printf("alt_pll_cntr_maxfreq.PeriphPLL_C3 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C4:
+ maxfreq->PeriphPLL_C4 = freq;
+ printf("alt_pll_cntr_maxfreq.PeriphPLL_C4 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_PERIPHERAL_PLL_C5:
+ maxfreq->PeriphPLL_C5 = freq;
+ printf("alt_pll_cntr_maxfreq.PeriphPLL_C5 = %10d\n", (unsigned int)freq);
+ break;
+
+ // SDRAM Clock Group
+ case ALT_CLK_SDRAM_PLL_C0:
+ maxfreq->SDRAMPLL_C0 = freq;
+ printf("alt_pll_cntr_maxfreq.SDRAMPLL_C0 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_SDRAM_PLL_C1:
+ maxfreq->SDRAMPLL_C1 = freq;
+ printf("alt_pll_cntr_maxfreq.SDRAMPLL_C1 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_SDRAM_PLL_C2:
+ maxfreq->SDRAMPLL_C2 = freq;
+ printf("alt_pll_cntr_maxfreq.SDRAMPLL_C2 = %10d\n", (unsigned int)freq);
+ break;
+ case ALT_CLK_SDRAM_PLL_C5:
+ maxfreq->SDRAMPLL_C5 = freq;
+ printf("alt_pll_cntr_maxfreq.SDRAMPLL_C5 = %10d\n", (unsigned int)freq);
+ break;
+ default:
+ ret = ALT_E_BAD_ARG;
+ printf("bad max frequency parameter\n");
+ break;
+ } // end of switch-case construct
+ }
+
+ return ret;
+}
+
+//
+// u-boot preloader actually initialize clock manager circuitry
+//
+// alt_clk_clkmgr_init() attempt to fix the pll counter max frequencies, since
+// thses frequencies are not known in advance until u-boot programmed clock manager.
+//
+ALT_STATUS_CODE alt_clk_clkmgr_init(void)
+{
+ ALT_STATUS_CODE ret = ALT_E_SUCCESS;
+ ALT_STATUS_CODE status ;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C0,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C1,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C2,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C3,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C4,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C5,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C0,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C1,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C2,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C3,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C4,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C5,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C0,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C1,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C2,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+ status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C5,&alt_pll_cntr_maxfreq );
+ if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
+
+
+ return ret;
+}
+