source: rtems/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_clock_manager.c @ 3eed4f3

5
Last change on this file since 3eed4f3 was 3eed4f3, checked in by Chris Johns <chrisj@…>, on 01/04/18 at 07:10:48

bsp/altera-cyclone-v: Use public include path

Update #3254.

  • Property mode set to 100644
File size: 207.0 KB
Line 
1/******************************************************************************
2 *
3 * Copyright 2013 Altera Corporation. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
23 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * OF SUCH DAMAGE.
28 *
29 ******************************************************************************/
30
31#include <stdint.h>
32#include <stdlib.h>
33#include <stdbool.h>
34#include <stdio.h>
35
36#include <bsp/socal/hps.h>
37#include <bsp/socal/socal.h>
38#include <bsp/socal/alt_sysmgr.h>
39#include <bsp/hwlib.h>
40#include <bsp/alt_clock_manager.h>
41#include <bsp/alt_mpu_registers.h>
42
43#define UINT12_MAX              (4096)
44
45/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
46/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Useful Structures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
47/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
48
49
50        /* General structure used to hold parameters of various clock entities, */
51typedef struct ALT_CLK_PARAMS_s
52{
53    alt_freq_t      freqcur;                   // current frequency of the clock
54    alt_freq_t      freqmin;                   // minimum allowed frequency for this clock
55    alt_freq_t      freqmax;                   // maximum allowed frequency for this clock
56    uint32_t        guardband : 7;             // guardband percentage (0-100) if this clock
57                                               //    is a PLL, ignored otherwise
58    uint32_t        active    : 1;             // current state of activity of this clock
59} ALT_CLK_PARAMS_t;
60
61
62typedef struct ALT_EXT_CLK_PARAMBLOK_s
63{
64    ALT_CLK_PARAMS_t        clkosc1;        // ALT_CLK_OSC1
65    ALT_CLK_PARAMS_t        clkosc2;        // ALT_CLK_OSC2
66    ALT_CLK_PARAMS_t        periph;         // ALT_CLK_F2H_PERIPH_REF
67    ALT_CLK_PARAMS_t        sdram;          // ALT_CLK_F2H_SDRAM_REF
68} ALT_EXT_CLK_PARAMBLOK_t;
69
70
71        /* Initializes the External Clock Frequency Limits block                        */
72        /* The first field is the current external clock frequency, and can be set by   */
73        /* alt_clk_ext_clk_freq_set(), the second and third fields are the minimum and  */
74        /* maximum frequencies, the fourth field is ignored, and the fifth field        */
75        /* contains the current activity state of the clock, 1=active, 0=inactive.      */
76        /* Values taken from Section 2.3 and Section 2.7.1 of the HHP HPS-Clocking      */
77        /* NPP specification.                                                           */
78static ALT_EXT_CLK_PARAMBLOK_t alt_ext_clk_paramblok =
79{
80    { 25000000, 10000000, 50000000, 0, 1 },
81    { 25000000, 10000000, 50000000, 0, 1 },
82    {        0, 10000000, 50000000, 0, 1 },
83    {        0, 10000000, 50000000, 0, 1 }
84};
85
86
87        /* PLL frequency limits */
88typedef struct ALT_PLL_CLK_PARAMBLOK_s
89{
90    ALT_CLK_PARAMS_t       MainPLL_600;         // Main PLL values for 600 MHz SoC
91    ALT_CLK_PARAMS_t       PeriphPLL_600;       // Peripheral PLL values for 600 MHz SoC
92    ALT_CLK_PARAMS_t       SDRAMPLL_600;        // SDRAM PLL values for 600 MHz SoC
93    ALT_CLK_PARAMS_t       MainPLL_800;         // Main PLL values for 800 MHz SoC
94    ALT_CLK_PARAMS_t       PeriphPLL_800;       // Peripheral PLL values for 800 MHz SoC
95    ALT_CLK_PARAMS_t       SDRAMPLL_800;        // SDRAM PLL values for 800 MHz SoC
96} ALT_PLL_CLK_PARAMBLOK_t;
97
98
99    /* Initializes the PLL frequency limits block                               */
100    /* The first field is the current frequency, the second and third fields    */
101    /* are the design limits of the PLLs as listed in Section 3.2.1.2 of the    */
102    /* HHP HPS-Clocking NPP document. The fourth field of each line is the      */
103    /* guardband percentage, and the fifth field of each line is the current    */
104    /* state of the PLL, 1=active, 0=inactive.                                  */
105#define     ALT_ORIGINAL_GUARDBAND_VAL      20
106#define     ALT_GUARDBAND_LIMIT             20
107
108static ALT_PLL_CLK_PARAMBLOK_t alt_pll_clk_paramblok =
109{
110    { 0, 320000000, 1200000000, ALT_ORIGINAL_GUARDBAND_VAL, 0 },
111    { 0, 320000000,  900000000, ALT_ORIGINAL_GUARDBAND_VAL, 0 },
112    { 0, 320000000,  800000000, ALT_ORIGINAL_GUARDBAND_VAL, 0 },
113    { 0, 320000000, 1600000000, ALT_ORIGINAL_GUARDBAND_VAL, 1 },
114    { 0, 320000000, 1250000000, ALT_ORIGINAL_GUARDBAND_VAL, 1 },
115    { 0, 320000000, 1066000000, ALT_ORIGINAL_GUARDBAND_VAL, 1 }
116};
117
118
119        /* PLL counter frequency limits */
120typedef struct ALT_PLL_CNTR_FREQMAX_s
121{
122    alt_freq_t       MainPLL_C0;         // Main PLL Counter 0 parameter block
123    alt_freq_t       MainPLL_C1;         // Main PLL Counter 1 parameter block
124    alt_freq_t       MainPLL_C2;         // Main PLL Counter 2 parameter block
125    alt_freq_t       MainPLL_C3;         // Main PLL Counter 3 parameter block
126    alt_freq_t       MainPLL_C4;         // Main PLL Counter 4 parameter block
127    alt_freq_t       MainPLL_C5;         // Main PLL Counter 5 parameter block
128    alt_freq_t       PeriphPLL_C0;       // Peripheral PLL Counter 0 parameter block
129    alt_freq_t       PeriphPLL_C1;       // Peripheral PLL Counter 1 parameter block
130    alt_freq_t       PeriphPLL_C2;       // Peripheral PLL Counter 2 parameter block
131    alt_freq_t       PeriphPLL_C3;       // Peripheral PLL Counter 3 parameter block
132    alt_freq_t       PeriphPLL_C4;       // Peripheral PLL Counter 4 parameter block
133    alt_freq_t       PeriphPLL_C5;       // Peripheral PLL Counter 5 parameter block
134    alt_freq_t       SDRAMPLL_C0;        // SDRAM PLL Counter 0 parameter block
135    alt_freq_t       SDRAMPLL_C1;        // SDRAM PLL Counter 1 parameter block
136    alt_freq_t       SDRAMPLL_C2;        // SDRAM PLL Counter 2 parameter block
137    alt_freq_t       SDRAMPLL_C5;        // SDRAM PLL Counter 5 parameter block
138} ALT_PLL_CNTR_FREQMAX_t;
139
140//
141// The following pll max frequency array statically defined must be recalculated each time
142// when powering up, by calling alt_clk_clkmgr_init()
143//
144// for 14.1 uboot preloader, the following values are calculated dynamically.
145//
146// Arrial 5
147// alt_pll_cntr_maxfreq.MainPLL_C0   = 1050000000
148// alt_pll_cntr_maxfreq.MainPLL_C1   =  350000000
149// alt_pll_cntr_maxfreq.MainPLL_C2   =  262500000
150// alt_pll_cntr_maxfreq.MainPLL_C3   =  350000000
151// alt_pll_cntr_maxfreq.MainPLL_C4   =    2050781
152// alt_pll_cntr_maxfreq.MainPLL_C5   =  116666666
153// alt_pll_cntr_maxfreq.PeriphPLL_C0 =    1953125
154// alt_pll_cntr_maxfreq.PeriphPLL_C1 =  250000000
155// alt_pll_cntr_maxfreq.PeriphPLL_C2 =    1953125
156// alt_pll_cntr_maxfreq.PeriphPLL_C3 =  200000000
157// alt_pll_cntr_maxfreq.PeriphPLL_C4 =  200000000
158// alt_pll_cntr_maxfreq.PeriphPLL_C5 =    1953125
159// alt_pll_cntr_maxfreq.SDRAMPLL_C0  =  533333333
160// alt_pll_cntr_maxfreq.SDRAMPLL_C1  = 1066666666
161// alt_pll_cntr_maxfreq.SDRAMPLL_C2  =  533333333
162// alt_pll_cntr_maxfreq.SDRAMPLL_C5  =  177777777
163
164// Cyclone V
165// alt_pll_cntr_maxfreq.MainPLL_C0   =  925000000
166// alt_pll_cntr_maxfreq.MainPLL_C1   =  370000000
167// alt_pll_cntr_maxfreq.MainPLL_C2   =  462500000
168// alt_pll_cntr_maxfreq.MainPLL_C3   =  370000000
169// alt_pll_cntr_maxfreq.MainPLL_C4   =    3613281
170// alt_pll_cntr_maxfreq.MainPLL_C5   =  123333333
171// alt_pll_cntr_maxfreq.PeriphPLL_C0 =    1953125
172// alt_pll_cntr_maxfreq.PeriphPLL_C1 =  250000000
173// alt_pll_cntr_maxfreq.PeriphPLL_C2 =    1953125
174// alt_pll_cntr_maxfreq.PeriphPLL_C3 =  200000000
175// alt_pll_cntr_maxfreq.PeriphPLL_C4 =  200000000
176// alt_pll_cntr_maxfreq.PeriphPLL_C5 =    1953125
177// alt_pll_cntr_maxfreq.SDRAMPLL_C0  =  400000000
178// alt_pll_cntr_maxfreq.SDRAMPLL_C1  =  800000000
179// alt_pll_cntr_maxfreq.SDRAMPLL_C2  =  400000000
180// alt_pll_cntr_maxfreq.SDRAMPLL_C5  =  133333333
181
182
183/* Initializes the PLL Counter output maximum frequency block  */
184static ALT_PLL_CNTR_FREQMAX_t alt_pll_cntr_maxfreq =
185{
186    800000000,    /* Main PLL Outputs */
187    400000000,
188    400000000,
189    432000000,
190    250000000,
191    125000000,
192    250000000,    /* Peripheral PLL Outputs */
193    250000000,
194    432000000,
195    250000000,
196    200000000,
197    100000000,    /* SDRAM PLL Outputs */
198    533000000,
199    1066000000,
200    533000000,
201    200000000
202};
203
204
205
206        /* Maximum multiply, divide, and counter divisor values for each PLL */
207#define     ALT_CLK_PLL_MULT_MAX        4095
208#define     ALT_CLK_PLL_DIV_MAX         63
209#define     ALT_CLK_PLL_CNTR_MAX        511
210
211
212        /* Definitions for the reset request and reset acknowledge bits    */
213        /* for each of the output counters for each of the PLLS            */
214#define     ALT_CLK_PLL_RST_BIT_C0      0x00000001
215#define     ALT_CLK_PLL_RST_BIT_C1      0x00000002
216#define     ALT_CLK_PLL_RST_BIT_C2      0x00000004
217#define     ALT_CLK_PLL_RST_BIT_C3      0x00000008
218#define     ALT_CLK_PLL_RST_BIT_C4      0x00000010
219#define     ALT_CLK_PLL_RST_BIT_C5      0x00000020
220
221
222        /* These are the bits that deal with PLL lock and this macro */
223        /* defines a mask to test for bits outside of these */
224#define ALT_CLK_MGR_PLL_LOCK_BITS  (ALT_CLKMGR_INTREN_MAINPLLACHIEVED_CLR_MSK \
225                                  & ALT_CLKMGR_INTREN_PERPLLACHIEVED_CLR_MSK \
226                                  & ALT_CLKMGR_INTREN_SDRPLLACHIEVED_CLR_MSK \
227                                  & ALT_CLKMGR_INTREN_MAINPLLLOST_CLR_MSK \
228                                  & ALT_CLKMGR_INTREN_PERPLLLOST_CLR_MSK \
229                                  & ALT_CLKMGR_INTREN_SDRPLLLOST_CLR_MSK)
230
231
232// Undocumented register which determines clock dividers for main PLL C0, C1, and C2. These should be considered RO.
233#define ALT_CLKMGR_ALTERA_OFST           0xe0
234#define ALT_CLKMGR_ALTERA_MPUCLK_OFST    0x0
235#define ALT_CLKMGR_ALTERA_MAINCLK_OFST   0x4
236#define ALT_CLKMGR_ALTERA_DBGATCLK_OFST  0x8
237#define ALT_CLKMGR_ALTERA_ADDR           ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ADDR) + ALT_CLKMGR_ALTERA_OFST))
238#define ALT_CLKMGR_ALTERA_MPUCLK_ADDR    ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ALTERA_ADDR) + ALT_CLKMGR_ALTERA_MPUCLK_OFST))
239#define ALT_CLKMGR_ALTERA_MAINCLK_ADDR   ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ALTERA_ADDR) + ALT_CLKMGR_ALTERA_MAINCLK_OFST))
240#define ALT_CLKMGR_ALTERA_DBGATCLK_ADDR  ALT_CAST(void *, (ALT_CAST(char *, ALT_CLKMGR_ALTERA_ADDR) + ALT_CLKMGR_ALTERA_DBGATCLK_OFST))
241#define ALT_CLKMGR_ALTERA_MPUCLK_CNT_GET(value)   (((value) & 0x000001ff) >> 0)
242#define ALT_CLKMGR_ALTERA_MAINCLK_CNT_GET(value)  (((value) & 0x000001ff) >> 0)
243#define ALT_CLKMGR_ALTERA_DBGATCLK_CNT_GET(value) (((value) & 0x000001ff) >> 0)
244
245/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
246/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Utility functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
247/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
248
249
250/****************************************************************************************/
251/* alt_clk_mgr_wait() introduces a delay, not very exact, but very light in             */
252/* implementation. Depending upon the optinization level, it will wait at least the     */
253/* number of clock cycles specified in the cnt parameter, sometimes many more. The      */
254/* reg parameter is set to a register or a memory location that was recently used (so   */
255/* as to avoid accidently evicting a register and a recently-used cache line in favor   */
256/* of one whose values are not actually needed.). The cnt parameter sets the number of  */
257/* repeated volatile memory reads and so sets a minimum time delay measured in          */
258/* mpu_clk cycles. If mpu_clk = osc1 clock (as in bypass mode), then this gives a       */
259/* minimum osc1 clock cycle delay.                                                      */
260/****************************************************************************************/
261
262inline static void alt_clk_mgr_wait(void* reg, uint32_t cnt)
263{
264    for (; cnt ; cnt--)
265    {
266        (void) alt_read_word(reg);
267    }
268}
269
270    /* Wait time constants */
271    /* These values came from Section 4.9.4 of the HHP HPS-Clocking NPP document */
272#define ALT_SW_MANAGED_CLK_WAIT_CTRDIV          30      /* 30 or more MPU clock cycles */
273#define ALT_SW_MANAGED_CLK_WAIT_HWCTRDIV        40
274#define ALT_SW_MANAGED_CLK_WAIT_BYPASS          30
275#define ALT_SW_MANAGED_CLK_WAIT_SAFEREQ         30
276#define ALT_SW_MANAGED_CLK_WAIT_SAFEEXIT        30
277#define ALT_SW_MANAGED_CLK_WAIT_NANDCLK         8       /* 8 or more MPU clock cycles */
278
279
280#define ALT_BYPASS_TIMEOUT_CNT      50
281        // arbitrary number until i find more info
282#define ALT_TIMEOUT_PHASE_SYNC      300
283        // how many loops to wait for the SDRAM clock to come around
284        // to zero and allow for writing a new divisor ratio to it
285
286ALT_STATUS_CODE alt_clk_plls_settle_wait(void)
287{
288    int32_t     i = ALT_BYPASS_TIMEOUT_CNT;
289    bool        nofini;
290
291    do
292    {
293        nofini = alt_read_word(ALT_CLKMGR_STAT_ADDR) & ALT_CLKMGR_STAT_BUSY_SET_MSK;
294    } while (nofini && i--);
295            // wait until clocks finish transitioning and become stable again
296    return (i > 0) ? ALT_E_SUCCESS : ALT_E_ERROR;
297}
298
299static ALT_STATUS_CODE alt_clk_pll_lock_wait(ALT_CLK_t pll, uint32_t timeout)
300{
301    uint32_t locked_mask = 0;
302
303    if      (pll == ALT_CLK_MAIN_PLL)       { locked_mask = ALT_CLKMGR_INTER_MAINPLLLOCKED_SET_MSK; }
304    else if (pll == ALT_CLK_PERIPHERAL_PLL) { locked_mask = ALT_CLKMGR_INTER_PERPLLLOCKED_SET_MSK; }
305    else if (pll == ALT_CLK_SDRAM_PLL)      { locked_mask = ALT_CLKMGR_INTER_SDRPLLLOCKED_SET_MSK; }
306    else
307    {
308        return ALT_E_BAD_ARG;
309    }
310
311    do
312    {
313        uint32_t int_status = alt_read_word(ALT_CLKMGR_INTER_ADDR);
314        if (int_status & locked_mask)
315        {
316            return ALT_E_SUCCESS;
317        }
318
319    } while (timeout--);
320
321    return ALT_E_TMO;
322}
323
324        /* Useful utility macro for checking if two values  */
325        /* are within a certain percentage of each other    */
326#define  alt_within_delta(ref, neu, prcnt)  (((((neu) * 100)/(ref)) < (100 + (prcnt))) \
327                                            && ((((neu) * 100)/(ref)) > (100 - (prcnt))))
328
329
330        /* Flags to include or omit code sections */
331// There are four cases where there is a small possibility of producing clock
332// glitches. Code has been added from an abundance of caution to prevent
333// these glitches. If further testing shows that this extra code is not necessary
334// under any conditions, it may be easily eliminated by clearing these flags.
335
336#define ALT_PREVENT_GLITCH_BYP              true
337// for PLL entering or leaving bypass
338#define ALT_PREVENT_GLITCH_EXSAFE           true
339// for PLL exiting safe mode
340#define ALT_PREVENT_GLITCH_CNTRRST          true
341// resets counter phase
342#define ALT_PREVENT_GLITCH_CHGC1            true
343// for changing Main PLL C1 counter
344
345
346
347/****************************************************************************************/
348/* Bare-bones utility function used to make the somewhat complex writes to the PLL      */
349/* counter registers (the clock dividers) easier. No parameter-checking or              */
350/* error-checking, this is a static to this file and invisible to Doxygen.              */
351/****************************************************************************************/
352
353static void alt_clk_pllcounter_write(void* vcoaddr, void* stataddr, void* cntraddr,
354        uint32_t val, uint32_t msk, uint32_t shift)
355{
356#if ALT_PREVENT_GLITCH_CNTRRST
357    // this is here from an abundance of caution and it may not be necessary
358    // to put the counter in reset for this write
359    volatile uint32_t   temp;
360
361    alt_setbits_word(vcoaddr, msk << shift);                // put the counter in reset
362    do
363    {
364        temp = alt_read_word(stataddr);
365    } while (!(temp & msk));
366
367    alt_write_word(cntraddr, val);
368    alt_clrbits_word(vcoaddr, msk << shift);                // release counter reset
369
370#else       // should we find out that resetting the counters as above is unnecessary
371    alt_write_word(cntraddr, val);
372#endif
373}
374
375
376/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
377/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Main Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
378/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
379
380
381/****************************************************************************************/
382/* alt_clk_lock_status_clear() clears assertions of one or more of the PLL lock status  */
383/* conditions.                                                                          */
384/****************************************************************************************/
385
386ALT_STATUS_CODE alt_clk_lock_status_clear(ALT_CLK_PLL_LOCK_STATUS_t lock_stat_mask)
387{
388    if (lock_stat_mask & (  ALT_CLKMGR_INTER_MAINPLLACHIEVED_CLR_MSK
389                          & ALT_CLKMGR_INTER_PERPLLACHIEVED_CLR_MSK
390                          & ALT_CLKMGR_INTER_SDRPLLACHIEVED_CLR_MSK
391                          & ALT_CLKMGR_INTER_MAINPLLLOST_CLR_MSK
392                          & ALT_CLKMGR_INTER_PERPLLLOST_CLR_MSK
393                          & ALT_CLKMGR_INTER_SDRPLLLOST_CLR_MSK)
394        )
395    {
396        return ALT_E_BAD_ARG;
397    }
398    else
399    {
400        alt_setbits_word(ALT_CLKMGR_INTER_ADDR, lock_stat_mask);
401        return ALT_E_SUCCESS;
402    }
403}
404
405
406/****************************************************************************************/
407/* alt_clk_lock_status_get() returns the value of the PLL lock status conditions.       */
408/****************************************************************************************/
409
410uint32_t alt_clk_lock_status_get(void)
411{
412    return alt_read_word(ALT_CLKMGR_INTER_ADDR) & (  ALT_CLKMGR_INTER_MAINPLLACHIEVED_SET_MSK
413                                                   | ALT_CLKMGR_INTER_PERPLLACHIEVED_SET_MSK
414                                                   | ALT_CLKMGR_INTER_SDRPLLACHIEVED_SET_MSK
415                                                   | ALT_CLKMGR_INTER_MAINPLLLOST_SET_MSK
416                                                   | ALT_CLKMGR_INTER_PERPLLLOST_SET_MSK
417                                                   | ALT_CLKMGR_INTER_SDRPLLLOST_SET_MSK
418                                                   | ALT_CLKMGR_INTER_MAINPLLLOCKED_SET_MSK
419                                                   | ALT_CLKMGR_INTER_PERPLLLOCKED_SET_MSK
420                                                   | ALT_CLKMGR_INTER_SDRPLLLOCKED_SET_MSK );
421}
422
423
424/****************************************************************************************/
425/* alt_clk_pll_is_locked() returns ALT_E_TRUE if the designated PLL is currently        */
426/* locked and ALT_E_FALSE if not.                                                       */
427/****************************************************************************************/
428
429ALT_STATUS_CODE alt_clk_pll_is_locked(ALT_CLK_t pll)
430{
431    ALT_STATUS_CODE status = ALT_E_BAD_ARG;
432
433    if (pll == ALT_CLK_MAIN_PLL)
434    {
435        status = (alt_read_word(ALT_CLKMGR_INTER_ADDR) & ALT_CLKMGR_INTER_MAINPLLLOCKED_SET_MSK)
436                ? ALT_E_TRUE : ALT_E_FALSE;
437    }
438    else if (pll == ALT_CLK_PERIPHERAL_PLL)
439    {
440        status = (alt_read_word(ALT_CLKMGR_INTER_ADDR) & ALT_CLKMGR_INTER_PERPLLLOCKED_SET_MSK)
441                ? ALT_E_TRUE : ALT_E_FALSE;
442    }
443    else if (pll == ALT_CLK_SDRAM_PLL)
444    {
445        status = (alt_read_word(ALT_CLKMGR_INTER_ADDR) & ALT_CLKMGR_INTER_SDRPLLLOCKED_SET_MSK)
446                ? ALT_E_TRUE : ALT_E_FALSE;
447    }
448    return status;
449}
450
451
452/****************************************************************************************/
453/* alt_clk_safe_mode_clear() clears the safe mode status of the Clock Manager following */
454/* a reset.                                                                             */
455/****************************************************************************************/
456
457ALT_STATUS_CODE alt_clk_safe_mode_clear(void)
458{
459    ALT_STATUS_CODE status = ALT_E_ERROR;
460#if ALT_PREVENT_GLITCH_EXSAFE
461    uint32_t        temp;
462
463    temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
464    alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp &
465            (ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK));
466                    // gate off l4MP and L4SP clocks (no matter their source)
467
468    alt_setbits_word(ALT_CLKMGR_CTL_ADDR, ALT_CLKMGR_CTL_SAFEMOD_SET_MSK);
469                    // clear safe mode bit
470    status = alt_clk_plls_settle_wait();
471    alt_replbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR,
472            ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK | ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK,
473            temp);
474                    // gate l4MP and L4SP clocks back on if they were on previously
475
476#else
477    alt_setbits_word(ALT_CLKMGR_CTL_ADDR, ALT_CLKMGR_CTL_SAFEMOD_SET_MSK);
478                    // clear safe mode bit
479    status = alt_clk_plls_settle_wait();
480
481#endif
482    return status;
483}
484
485
486/****************************************************************************************/
487/* alt_clk_is_in_safe_mode() returns whether the specified safe mode clock domain is in */
488/* safe mode or not.                                                                    */
489/****************************************************************************************/
490
491bool alt_clk_is_in_safe_mode(ALT_CLK_SAFE_DOMAIN_t clk_domain)
492{
493    bool        ret = false;
494    uint32_t    temp;
495
496    if (clk_domain == ALT_CLK_DOMAIN_NORMAL)
497    {
498        ret = alt_read_word(ALT_CLKMGR_CTL_ADDR) & ALT_CLKMGR_CTL_SAFEMOD_SET_MSK;
499                // is the main clock domain in safe mode?
500    }
501    else if (clk_domain == ALT_CLK_DOMAIN_DEBUG)
502    {
503        temp = alt_read_word(ALT_CLKMGR_DBCTL_ADDR);
504        if (temp & ALT_CLKMGR_DBCTL_STAYOSC1_SET_MSK)
505        {
506            ret = true;                // is the debug clock domain in safe mode?
507        }
508        else if (temp & ALT_CLKMGR_DBCTL_ENSFMDWR_SET_MSK)
509        {
510            ret = alt_read_word(ALT_CLKMGR_CTL_ADDR) & ALT_CLKMGR_CTL_SAFEMOD_SET_MSK;
511                    // is the debug clock domain following the main clock domain
512                    // AND is the main clock domain in safe mode?
513        }
514    }
515    return ret;
516}
517
518/****************************************************************************************/
519/* alt_clk_pll_bypass_disable() disables bypass mode for the specified PLL, removing    */
520/* it from bypass mode and allowing it to provide the output of the PLL to drive the    */
521/* six main clocks.                                                                     */
522/****************************************************************************************/
523
524ALT_STATUS_CODE alt_clk_pll_bypass_disable(ALT_CLK_t pll)
525{
526    ALT_STATUS_CODE status = ALT_E_BAD_ARG;
527    uint32_t        temp;
528#if  ALT_PREVENT_GLITCH_BYP
529    uint32_t        temp1;
530    bool            restore_0 = false;
531    bool            restore_1 = false;
532#endif
533
534    // this function should only be called after the selected PLL is locked
535    if (alt_clk_pll_is_locked(pll) == ALT_E_TRUE)
536    {
537        if (pll == ALT_CLK_MAIN_PLL)
538        {
539#if  ALT_PREVENT_GLITCH_BYP
540            // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
541            // bypass state, then gate clock back on. FogBugz #63778
542            temp  = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
543            temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
544
545            if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK)))
546            {
547                restore_0 = true;
548            }
549            if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK)))
550            {
551                restore_1 = true;
552            }
553            temp = temp1;
554            if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
555            if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
556            if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
557#endif
558
559            // assert outresetall of main PLL
560            temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
561            alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, temp | ALT_CLKMGR_MAINPLL_VCO_OUTRSTALL_SET_MSK);
562
563            // deassert outresetall of main PLL
564            alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, temp & ALT_CLKMGR_MAINPLL_VCO_OUTRSTALL_CLR_MSK);
565
566            alt_clk_plls_settle_wait();
567
568            // remove bypass
569            alt_clrbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_MAINPLL_SET_MSK);
570            status = alt_clk_plls_settle_wait();
571
572#if  ALT_PREVENT_GLITCH_BYP
573            if (restore_0 || restore_1)
574            {
575                alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
576                            // wait a bit more before reenabling the L4MP and L4SP clocks
577                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1);
578            }
579#endif
580        }
581
582        else if (pll == ALT_CLK_PERIPHERAL_PLL)
583        {
584#if  ALT_PREVENT_GLITCH_BYP
585            // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
586            // bypass state, then gate clock back on. FogBugz #63778
587            temp = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
588            temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
589
590            if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK))
591            {
592                    restore_0 = true;
593            }
594            if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK))
595            {
596                    restore_1 = true;
597            }
598            temp = temp1;
599            if (restore_0)  { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
600            if (restore_1)  { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
601            if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
602#endif
603
604            // assert outresetall of Peripheral PLL
605            temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
606            alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp | ALT_CLKMGR_PERPLL_VCO_OUTRSTALL_SET_MSK);
607            alt_clk_plls_settle_wait();
608
609            // deassert outresetall of main PLL
610            alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp & ALT_CLKMGR_PERPLL_VCO_OUTRSTALL_CLR_MSK);
611
612            // remove bypass - don't think that there's any need to touch the bypass clock source
613            alt_clrbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_PERPLL_SET_MSK);
614            status = alt_clk_plls_settle_wait();
615
616#if  ALT_PREVENT_GLITCH_BYP
617            if (restore_0 || restore_1)
618            {
619                alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
620                            // wait a bit more before reenabling the L4MP and L4SP clocks
621                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1);
622            }
623#endif
624        }
625
626        else if (pll == ALT_CLK_SDRAM_PLL)
627        {
628            // assert outresetall of SDRAM PLL
629            temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
630            alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp | ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_SET_MSK);
631
632            // deassert outresetall of main PLL
633            alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp & ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_CLR_MSK);
634            alt_clk_plls_settle_wait();
635
636            // remove bypass - don't think that there's any need to touch the bypass clock source
637            alt_clrbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_SDRPLLSRC_SET_MSK);
638            status = alt_clk_plls_settle_wait();
639        }
640    }
641    else
642    {
643        status = ALT_E_ERROR;
644    }
645
646    return status;
647}
648
649
650/****************************************************************************************/
651/* alt_clk_pll_bypass_enable() enable bypass mode for the specified PLL.                */
652/****************************************************************************************/
653
654ALT_STATUS_CODE alt_clk_pll_bypass_enable(ALT_CLK_t pll, bool use_input_mux)
655{
656    ALT_STATUS_CODE status = ALT_E_BAD_ARG;
657    uint32_t        temp;
658#ifdef  ALT_PREVENT_GLITCH_BYP
659    uint32_t        temp1;
660    bool            restore_0 = false;
661    bool            restore_1 = false;
662#endif
663
664    if (pll == ALT_CLK_MAIN_PLL)
665    {
666        if (!use_input_mux)
667        {
668#ifdef  ALT_PREVENT_GLITCH_BYP
669            // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
670            // bypass state, then gate clock back on. FogBugz #63778
671            temp  = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
672            temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
673
674            if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK)))
675            {
676                restore_0 = true;
677            }
678            if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK)))
679            {
680                restore_1 = true;
681            }
682            temp = temp1;
683            if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
684            if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
685            if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
686
687            alt_setbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_MAINPLL_SET_MSK);
688                        // no input mux select on main PLL
689
690            status = alt_clk_plls_settle_wait();
691                        // wait before reenabling the L4MP and L4SP clocks
692            if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1); }
693
694#else
695            alt_setbits_word(ALT_CLKMGR_BYPASS_ADDR, ALT_CLKMGR_BYPASS_MAINPLL_SET_MSK);
696                        // no input mux select on main PLL
697            status = alt_clk_plls_settle_wait();
698
699#endif
700            status = ALT_E_SUCCESS;
701        }
702        else
703        {
704            status =  ALT_E_BAD_ARG;
705        }
706    }
707    else if (pll == ALT_CLK_PERIPHERAL_PLL)
708    {
709#ifdef  ALT_PREVENT_GLITCH_BYP
710        // if L4MP or L4SP source is set to Peripheral PLL C1, gate it off before changing
711        // bypass state, then gate clock back on. FogBugz #63778
712        temp  = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
713        temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
714
715        if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK))
716        {
717            restore_0 = true;
718        }
719        if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK))
720        {
721            restore_1 = true;
722        }
723        temp = temp1;
724        if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
725        if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
726        if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
727
728        temp = alt_read_word(ALT_CLKMGR_BYPASS_ADDR) &
729                (ALT_CLKMGR_BYPASS_PERPLL_CLR_MSK & ALT_CLKMGR_BYPASS_PERPLLSRC_CLR_MSK);
730        temp |= (use_input_mux) ? ALT_CLKMGR_BYPASS_PERPLL_SET_MSK |
731                ALT_CLKMGR_BYPASS_PERPLLSRC_SET_MSK : ALT_CLKMGR_BYPASS_PERPLL_SET_MSK;
732                    // set bypass bit and optionally the source select bit
733
734        alt_write_word(ALT_CLKMGR_BYPASS_ADDR, temp);
735        alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
736                    // wait a bit before reenabling the L4MP and L4SP clocks
737        if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1); }
738
739#else
740        temp = alt_read_word(ALT_CLKMGR_BYPASS_ADDR) &
741                (ALT_CLKMGR_BYPASS_PERPLL_CLR_MSK & ALT_CLKMGR_BYPASS_PERPLLSRC_CLR_MSK);
742        temp |= (use_input_mux) ? ALT_CLKMGR_BYPASS_PERPLL_SET_MSK |
743                ALT_CLKMGR_BYPASS_PERPLLSRC_SET_MSK : ALT_CLKMGR_BYPASS_PERPLL_SET_MSK;
744                    // set bypass bit and optionally the source select bit
745#endif
746        status = ALT_E_SUCCESS;
747    }
748
749    else if (pll == ALT_CLK_SDRAM_PLL)
750    {
751        temp = alt_read_word(ALT_CLKMGR_BYPASS_ADDR) &
752                (ALT_CLKMGR_BYPASS_SDRPLL_CLR_MSK & ALT_CLKMGR_BYPASS_SDRPLLSRC_CLR_MSK);
753        temp |= (use_input_mux) ? ALT_CLKMGR_BYPASS_SDRPLL_SET_MSK |
754                ALT_CLKMGR_BYPASS_SDRPLLSRC_SET_MSK : ALT_CLKMGR_BYPASS_SDRPLL_SET_MSK;
755                    // set bypass bit and optionally the source select bit
756        alt_write_word(ALT_CLKMGR_BYPASS_ADDR, temp);
757        status = ALT_E_SUCCESS;
758    }
759    return status;
760}
761
762
763/****************************************************************************************/
764/* alt_clk_pll_is_bypassed() returns whether the specified PLL is in bypass or not.     */
765/* Bypass is a special state where the PLL VCO and the C0-C5 counters are bypassed      */
766/* and not in the circuit. Either the Osc1 clock input or the input chosen by the       */
767/* input mux may be selected to be operational in the bypass state. All changes to      */
768/* the PLL VCO must be made in bypass mode to avoid the potential of producing clock    */
769/* glitches which may affect downstream clock dividers and peripherals.                 */
770/****************************************************************************************/
771
772ALT_STATUS_CODE alt_clk_pll_is_bypassed(ALT_CLK_t pll)
773{
774    ALT_STATUS_CODE status = ALT_E_BAD_ARG;
775
776    if (pll == ALT_CLK_MAIN_PLL)
777    {
778        status = (ALT_CLKMGR_CTL_SAFEMOD_GET(alt_read_word(ALT_CLKMGR_CTL_ADDR))
779                || ALT_CLKMGR_BYPASS_MAINPLL_GET(alt_read_word(ALT_CLKMGR_BYPASS_ADDR)))
780                ? ALT_E_TRUE : ALT_E_FALSE;
781    }
782    else if (pll == ALT_CLK_PERIPHERAL_PLL)
783    {
784        status = (ALT_CLKMGR_CTL_SAFEMOD_GET(alt_read_word(ALT_CLKMGR_CTL_ADDR))
785                || ALT_CLKMGR_BYPASS_PERPLL_GET(alt_read_word(ALT_CLKMGR_BYPASS_ADDR)))
786                ? ALT_E_TRUE : ALT_E_FALSE;
787    }
788    else if (pll == ALT_CLK_SDRAM_PLL)
789    {
790        status = (ALT_CLKMGR_CTL_SAFEMOD_GET(alt_read_word(ALT_CLKMGR_CTL_ADDR))
791                || ALT_CLKMGR_BYPASS_SDRPLL_GET(alt_read_word(ALT_CLKMGR_BYPASS_ADDR)))
792                ? ALT_E_TRUE : ALT_E_FALSE;
793    }
794    return status;
795}
796
797
798/****************************************************************************************/
799/* alt_clk_pll_source_get() returns the current input of the specified PLL.             */
800/****************************************************************************************/
801
802ALT_CLK_t alt_clk_pll_source_get(ALT_CLK_t pll)
803{
804    ALT_CLK_t      ret = ALT_CLK_UNKNOWN;
805    uint32_t       temp;
806
807
808    if (pll == ALT_CLK_MAIN_PLL)
809    {
810        ret = ALT_CLK_IN_PIN_OSC1;
811    }
812    else if (pll == ALT_CLK_PERIPHERAL_PLL)
813    {
814        // three possible clock sources for the peripheral PLL
815        temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR));
816        if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
817        {
818            ret = ALT_CLK_IN_PIN_OSC1;
819        }
820        else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
821        {
822            ret = ALT_CLK_IN_PIN_OSC2;
823        }
824        else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
825        {
826            ret = ALT_CLK_F2H_PERIPH_REF;
827        }
828    }
829    else if (pll == ALT_CLK_SDRAM_PLL)
830    {
831        // three possible clock sources for the SDRAM PLL
832        temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
833        if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
834        {
835            ret = ALT_CLK_IN_PIN_OSC1;
836        }
837        else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
838        {
839            ret = ALT_CLK_IN_PIN_OSC2;
840        }
841        else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
842        {
843            ret = ALT_CLK_F2H_SDRAM_REF;
844        }
845    }
846    return ret;
847}
848
849//
850// alt_clk_clock_disable() disables the specified clock. Once the clock is disabled,
851// its clock signal does not propagate to its clocked elements.
852//
853ALT_STATUS_CODE alt_clk_clock_disable(ALT_CLK_t clk)
854{
855    ALT_STATUS_CODE status = ALT_E_SUCCESS;
856
857    switch (clk)
858    {
859        // For PLLs, put them in bypass mode.
860    case ALT_CLK_MAIN_PLL:
861    case ALT_CLK_PERIPHERAL_PLL:
862    case ALT_CLK_SDRAM_PLL:
863        status = alt_clk_pll_bypass_enable(clk, false);
864        break;
865
866        // Clocks that originate at the Main PLL.
867    case ALT_CLK_L4_MAIN:
868        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MAINCLK_SET_MSK);
869        break;
870    case ALT_CLK_L3_MP:
871        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L3MPCLK_SET_MSK);
872        break;
873    case ALT_CLK_L4_MP:
874        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK);
875        break;
876    case ALT_CLK_L4_SP:
877        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK);
878        break;
879    case ALT_CLK_DBG_AT:
880        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGATCLK_SET_MSK);
881        break;
882    case ALT_CLK_DBG:
883        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGCLK_SET_MSK);
884        break;
885    case ALT_CLK_DBG_TRACE:
886        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_SET_MSK);
887        break;
888    case ALT_CLK_DBG_TIMER:
889        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTMRCLK_SET_MSK);
890        break;
891    case ALT_CLK_CFG:
892        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_CFGCLK_SET_MSK);
893        break;
894    case ALT_CLK_H2F_USER0:
895        alt_clrbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_SET_MSK);
896        break;
897
898        // Clocks that originate at the Peripheral PLL.
899    case ALT_CLK_EMAC0:
900        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC0CLK_SET_MSK);
901        break;
902    case ALT_CLK_EMAC1:
903        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC1CLK_SET_MSK);
904        break;
905    case ALT_CLK_USB_MP:
906        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK);
907        break;
908    case ALT_CLK_SPI_M:
909        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK);
910        break;
911    case ALT_CLK_CAN0:
912        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK);
913        break;
914    case ALT_CLK_CAN1:
915        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK);
916        break;
917    case ALT_CLK_GPIO_DB:
918        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK);
919        break;
920    case ALT_CLK_H2F_USER1:
921        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_SET_MSK);
922        break;
923    case ALT_CLK_SDMMC:
924        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK);
925        break;
926    case ALT_CLK_NAND_X:
927        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
928        alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
929        // gate nand_clk off before nand_x_clk.
930        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
931        break;
932    case ALT_CLK_NAND:
933        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
934        break;
935    case ALT_CLK_QSPI:
936        alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
937        break;
938
939        // Clocks that originate at the SDRAM PLL.
940    case ALT_CLK_DDR_DQS:
941        alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_SET_MSK);
942        break;
943    case ALT_CLK_DDR_2X_DQS:
944        alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_SET_MSK);
945        break;
946    case ALT_CLK_DDR_DQ:
947        alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_SET_MSK);
948        break;
949    case ALT_CLK_H2F_USER2:
950        alt_clrbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_SET_MSK);
951        break;
952
953    default:
954        status = ALT_E_BAD_ARG;
955        break;
956    }
957
958    return status;
959}
960
961
962//
963// alt_clk_clock_enable() enables the specified clock. Once the clock is enabled, its
964// clock signal propagates to its elements.
965//
966ALT_STATUS_CODE alt_clk_clock_enable(ALT_CLK_t clk)
967{
968    ALT_STATUS_CODE status = ALT_E_SUCCESS;
969
970    switch (clk)
971    {
972        // For PLLs, take them out of bypass mode.
973    case ALT_CLK_MAIN_PLL:
974    case ALT_CLK_PERIPHERAL_PLL:
975    case ALT_CLK_SDRAM_PLL:
976        status = alt_clk_pll_bypass_disable(clk);
977        break;
978
979        // Clocks that originate at the Main PLL.
980    case ALT_CLK_L4_MAIN:
981        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MAINCLK_SET_MSK);
982        break;
983    case ALT_CLK_L3_MP:
984        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L3MPCLK_SET_MSK);
985        break;
986    case ALT_CLK_L4_MP:
987        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK);
988        break;
989    case ALT_CLK_L4_SP:
990        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK);
991        break;
992    case ALT_CLK_DBG_AT:
993        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGATCLK_SET_MSK);
994        break;
995    case ALT_CLK_DBG:
996        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGCLK_SET_MSK);
997        break;
998    case ALT_CLK_DBG_TRACE:
999        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_SET_MSK);
1000        break;
1001    case ALT_CLK_DBG_TIMER:
1002        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_DBGTMRCLK_SET_MSK);
1003        break;
1004    case ALT_CLK_CFG:
1005        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_CFGCLK_SET_MSK);
1006        break;
1007    case ALT_CLK_H2F_USER0:
1008        alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_SET_MSK);
1009        break;
1010
1011        // Clocks that originate at the Peripheral PLL.
1012    case ALT_CLK_EMAC0:
1013        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC0CLK_SET_MSK);
1014        break;
1015    case ALT_CLK_EMAC1:
1016        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_EMAC1CLK_SET_MSK);
1017        break;
1018    case ALT_CLK_USB_MP:
1019        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK);
1020        break;
1021    case ALT_CLK_SPI_M:
1022        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK);
1023        break;
1024    case ALT_CLK_CAN0:
1025        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK);
1026        break;
1027    case ALT_CLK_CAN1:
1028        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK);
1029        break;
1030    case ALT_CLK_GPIO_DB:
1031        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK);
1032        break;
1033    case ALT_CLK_H2F_USER1:
1034        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_SET_MSK);
1035        break;
1036    case ALT_CLK_SDMMC:
1037        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK);
1038        break;
1039    case ALT_CLK_NAND_X:
1040        // implementation detail - should ALK_CLK_NAND be gated off here before enabling ALT_CLK_NAND_X?
1041        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
1042        // implementation detail - should this wait be enforced here?
1043        alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
1044        break;
1045    case ALT_CLK_NAND:
1046        // enabling ALT_CLK_NAND always implies enabling ALT_CLK_NAND_X first
1047        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
1048        alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
1049        // gate nand_x_clk on at least 8 MCU clocks before nand_clk
1050        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
1051        break;
1052    case ALT_CLK_QSPI:
1053        alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
1054        break;
1055
1056        // Clocks that originate at the SDRAM PLL.
1057    case ALT_CLK_DDR_DQS:
1058        alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_SET_MSK);
1059        break;
1060    case ALT_CLK_DDR_2X_DQS:
1061        alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_SET_MSK);
1062        break;
1063    case ALT_CLK_DDR_DQ:
1064        alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_SET_MSK);
1065        break;
1066    case ALT_CLK_H2F_USER2:
1067        alt_setbits_word(ALT_CLKMGR_SDRPLL_EN_ADDR, ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_SET_MSK);
1068        break;
1069
1070    default:
1071        status = ALT_E_BAD_ARG;
1072        break;
1073    }
1074
1075    return status;
1076}
1077
1078//
1079// alt_clk_is_enabled() returns whether the specified clock is enabled or not.
1080//
1081ALT_STATUS_CODE alt_clk_is_enabled(ALT_CLK_t clk)
1082{
1083    ALT_STATUS_CODE status = ALT_E_BAD_ARG;
1084
1085    switch (clk)
1086    {
1087        // For PLLs, this function checks if the PLL is bypassed or not.
1088    case ALT_CLK_MAIN_PLL:
1089    case ALT_CLK_PERIPHERAL_PLL:
1090    case ALT_CLK_SDRAM_PLL:
1091        status = (alt_clk_pll_is_bypassed(clk) != ALT_E_TRUE);
1092        break;
1093
1094        // These clocks are not gated, so must return a ALT_E_BAD_ARG type error.
1095    case ALT_CLK_MAIN_PLL_C0:
1096    case ALT_CLK_MAIN_PLL_C1:
1097    case ALT_CLK_MAIN_PLL_C2:
1098    case ALT_CLK_MAIN_PLL_C3:
1099    case ALT_CLK_MAIN_PLL_C4:
1100    case ALT_CLK_MAIN_PLL_C5:
1101    case ALT_CLK_MPU:
1102    case ALT_CLK_MPU_L2_RAM:
1103    case ALT_CLK_MPU_PERIPH:
1104    case ALT_CLK_L3_MAIN:
1105    case ALT_CLK_L3_SP:
1106    case ALT_CLK_DBG_BASE:
1107    case ALT_CLK_MAIN_QSPI:
1108    case ALT_CLK_MAIN_NAND_SDMMC:
1109    case ALT_CLK_PERIPHERAL_PLL_C0:
1110    case ALT_CLK_PERIPHERAL_PLL_C1:
1111    case ALT_CLK_PERIPHERAL_PLL_C2:
1112    case ALT_CLK_PERIPHERAL_PLL_C3:
1113    case ALT_CLK_PERIPHERAL_PLL_C4:
1114    case ALT_CLK_PERIPHERAL_PLL_C5:
1115    case ALT_CLK_SDRAM_PLL_C0:
1116    case ALT_CLK_SDRAM_PLL_C1:
1117    case ALT_CLK_SDRAM_PLL_C2:
1118    case ALT_CLK_SDRAM_PLL_C5:
1119        status = ALT_E_BAD_ARG;
1120        break;
1121
1122        // Clocks that originate at the Main PLL.
1123    case ALT_CLK_L4_MAIN:
1124        status = (ALT_CLKMGR_MAINPLL_EN_L4MAINCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1125            ? ALT_E_TRUE : ALT_E_FALSE;
1126        break;
1127    case ALT_CLK_L3_MP:
1128        status = (ALT_CLKMGR_MAINPLL_EN_L3MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1129            ? ALT_E_TRUE : ALT_E_FALSE;
1130        break;
1131    case ALT_CLK_L4_MP:
1132        status = (ALT_CLKMGR_MAINPLL_EN_L4MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1133            ? ALT_E_TRUE : ALT_E_FALSE;
1134        break;
1135    case ALT_CLK_L4_SP:
1136        status = (ALT_CLKMGR_MAINPLL_EN_L4SPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1137            ? ALT_E_TRUE : ALT_E_FALSE;
1138        break;
1139    case ALT_CLK_DBG_AT:
1140        status = (ALT_CLKMGR_MAINPLL_EN_DBGATCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1141            ? ALT_E_TRUE : ALT_E_FALSE;
1142        break;
1143    case ALT_CLK_DBG:
1144        status = (ALT_CLKMGR_MAINPLL_EN_DBGCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1145            ? ALT_E_TRUE : ALT_E_FALSE;
1146        break;
1147    case ALT_CLK_DBG_TRACE:
1148        status = (ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1149            ? ALT_E_TRUE : ALT_E_FALSE;
1150        break;
1151    case ALT_CLK_DBG_TIMER:
1152        status = (ALT_CLKMGR_MAINPLL_EN_DBGTMRCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1153            ? ALT_E_TRUE : ALT_E_FALSE;
1154        break;
1155    case ALT_CLK_CFG:
1156        status = (ALT_CLKMGR_MAINPLL_EN_CFGCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1157            ? ALT_E_TRUE : ALT_E_FALSE;
1158        break;
1159    case ALT_CLK_H2F_USER0:
1160        status = (ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR)))
1161            ? ALT_E_TRUE : ALT_E_FALSE;
1162        break;
1163
1164        // Clocks that originate at the Peripheral PLL.
1165    case ALT_CLK_EMAC0:
1166        status = (ALT_CLKMGR_PERPLL_EN_EMAC0CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1167            ? ALT_E_TRUE : ALT_E_FALSE;
1168        break;
1169    case ALT_CLK_EMAC1:
1170        status = (ALT_CLKMGR_PERPLL_EN_EMAC1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1171            ? ALT_E_TRUE : ALT_E_FALSE;
1172        break;
1173    case ALT_CLK_USB_MP:
1174        status = (ALT_CLKMGR_PERPLL_EN_USBCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1175            ? ALT_E_TRUE : ALT_E_FALSE;
1176        break;
1177    case ALT_CLK_SPI_M:
1178        status = (ALT_CLKMGR_PERPLL_EN_SPIMCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1179            ? ALT_E_TRUE : ALT_E_FALSE;
1180        break;
1181    case ALT_CLK_CAN0:
1182        status = (ALT_CLKMGR_PERPLL_EN_CAN0CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1183            ? ALT_E_TRUE : ALT_E_FALSE;
1184        break;
1185    case ALT_CLK_CAN1:
1186        status = (ALT_CLKMGR_PERPLL_EN_CAN1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1187            ? ALT_E_TRUE : ALT_E_FALSE;
1188        break;
1189    case ALT_CLK_GPIO_DB:
1190        status = (ALT_CLKMGR_PERPLL_EN_GPIOCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1191            ? ALT_E_TRUE : ALT_E_FALSE;
1192        break;
1193    case ALT_CLK_H2F_USER1:
1194        status = (ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1195            ? ALT_E_TRUE : ALT_E_FALSE;
1196        break;
1197
1198        // Clocks that may originate at the Main PLL, the Peripheral PLL, or the FPGA.
1199    case ALT_CLK_SDMMC:
1200        status = (ALT_CLKMGR_PERPLL_EN_SDMMCCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1201            ? ALT_E_TRUE : ALT_E_FALSE;
1202        break;
1203    case ALT_CLK_NAND_X:
1204        status = (ALT_CLKMGR_PERPLL_EN_NANDXCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1205            ? ALT_E_TRUE : ALT_E_FALSE;
1206        break;
1207    case ALT_CLK_NAND:
1208        status = (ALT_CLKMGR_PERPLL_EN_NANDCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1209            ? ALT_E_TRUE : ALT_E_FALSE;
1210        break;
1211    case ALT_CLK_QSPI:
1212        status = (ALT_CLKMGR_PERPLL_EN_QSPICLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)))
1213            ? ALT_E_TRUE : ALT_E_FALSE;
1214        break;
1215
1216        // Clocks that originate at the SDRAM PLL.
1217    case ALT_CLK_DDR_DQS:
1218        status = (ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
1219            ? ALT_E_TRUE : ALT_E_FALSE;
1220        break;
1221    case ALT_CLK_DDR_2X_DQS:
1222        status = (ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
1223            ? ALT_E_TRUE : ALT_E_FALSE;
1224        break;
1225    case ALT_CLK_DDR_DQ:
1226        status = (ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
1227            ? ALT_E_TRUE : ALT_E_FALSE;
1228        break;
1229    case ALT_CLK_H2F_USER2:
1230        status = (ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_GET(alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR)))
1231            ? ALT_E_TRUE : ALT_E_FALSE;
1232        break;
1233
1234    default:
1235        status = ALT_E_BAD_ARG;
1236        break;
1237
1238    }
1239
1240    return status;
1241}
1242
1243//
1244// alt_clk_source_get() gets the input reference clock source selection value for the
1245// specified clock or PLL.
1246//
1247ALT_CLK_t alt_clk_source_get(ALT_CLK_t clk)
1248{
1249    ALT_CLK_t ret = ALT_CLK_UNKNOWN;
1250    uint32_t  temp;
1251
1252    switch (clk)
1253    {
1254        // Potential external clock sources.
1255        // these clock entities are their own source
1256    case ALT_CLK_IN_PIN_OSC1:
1257    case ALT_CLK_IN_PIN_OSC2:
1258    case ALT_CLK_F2H_PERIPH_REF:
1259    case ALT_CLK_F2H_SDRAM_REF:
1260    case ALT_CLK_IN_PIN_JTAG:
1261    case ALT_CLK_IN_PIN_ULPI0:
1262    case ALT_CLK_IN_PIN_ULPI1:
1263    case ALT_CLK_IN_PIN_EMAC0_RX:
1264    case ALT_CLK_IN_PIN_EMAC1_RX:
1265        ret = clk;
1266        break;
1267
1268        // Phase-Locked Loops.
1269    case ALT_CLK_MAIN_PLL:
1270    case ALT_CLK_OSC1:
1271        ret = ALT_CLK_IN_PIN_OSC1;
1272        break;
1273    case ALT_CLK_PERIPHERAL_PLL:
1274        ret = alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL);
1275        break;
1276    case ALT_CLK_SDRAM_PLL:
1277        ret = alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL);
1278        break;
1279
1280        // Main Clock Group.
1281    case ALT_CLK_MAIN_PLL_C0:
1282    case ALT_CLK_MAIN_PLL_C1:
1283    case ALT_CLK_MAIN_PLL_C2:
1284    case ALT_CLK_MAIN_PLL_C3:
1285    case ALT_CLK_MAIN_PLL_C4:
1286    case ALT_CLK_MAIN_PLL_C5:
1287        // check bypass, return either osc1 or PLL ID
1288        ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1289            ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL;
1290        break;
1291
1292    case ALT_CLK_MPU_PERIPH:
1293    case ALT_CLK_MPU_L2_RAM:
1294    case ALT_CLK_MPU:
1295        ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1296            ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C0;
1297        break;
1298
1299    case ALT_CLK_L4_MAIN:
1300    case ALT_CLK_L3_MAIN:
1301    case ALT_CLK_L3_MP:
1302    case ALT_CLK_L3_SP:
1303        ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1304            ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C1;
1305        break;
1306
1307    case ALT_CLK_L4_MP:
1308        // read the state of the L4_mp source bit
1309        if ((ALT_CLKMGR_MAINPLL_L4SRC_L4MP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR)))
1310            == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_MAINPLL)
1311        {
1312            ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1313                ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C1;
1314        }
1315        else
1316        {
1317            // if the clock comes from periph_base_clk
1318            ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1319                alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C4;
1320        }
1321        break;
1322
1323    case ALT_CLK_L4_SP:
1324        // read the state of the source bit
1325        if ((ALT_CLKMGR_MAINPLL_L4SRC_L4SP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR)))
1326            == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_MAINPLL)
1327        {
1328            ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1329                ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C1;
1330        }
1331        else
1332        {
1333            // if the clock comes from periph_base_clk
1334            ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1335                alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL_C4;
1336        }
1337        break;
1338
1339    case ALT_CLK_DBG_BASE:
1340    case ALT_CLK_DBG_AT:
1341    case ALT_CLK_DBG_TRACE:
1342    case ALT_CLK_DBG_TIMER:
1343    case ALT_CLK_DBG:
1344        ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1345            ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C2;
1346        break;
1347    case ALT_CLK_MAIN_QSPI:
1348        ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1349            ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C3;
1350        break;
1351    case ALT_CLK_MAIN_NAND_SDMMC:
1352        ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1353            ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C4;
1354        break;
1355    case ALT_CLK_CFG:
1356    case ALT_CLK_H2F_USER0:
1357        ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1358            ALT_CLK_OSC1 : ALT_CLK_MAIN_PLL_C5;
1359        break;
1360
1361        // Peripherals Clock Group
1362    case ALT_CLK_PERIPHERAL_PLL_C0:
1363    case ALT_CLK_PERIPHERAL_PLL_C1:
1364    case ALT_CLK_PERIPHERAL_PLL_C2:
1365    case ALT_CLK_PERIPHERAL_PLL_C3:
1366    case ALT_CLK_PERIPHERAL_PLL_C4:
1367    case ALT_CLK_PERIPHERAL_PLL_C5:
1368        // if the clock comes from periph_base_clk
1369        ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1370            alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) : ALT_CLK_PERIPHERAL_PLL;
1371        break;
1372
1373    case ALT_CLK_EMAC0:
1374        ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1375            alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) :  ALT_CLK_PERIPHERAL_PLL_C0;
1376        break;
1377
1378    case ALT_CLK_EMAC1:
1379        ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1380            alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) :  ALT_CLK_PERIPHERAL_PLL_C1;
1381        break;
1382
1383    case ALT_CLK_USB_MP:
1384    case ALT_CLK_SPI_M:
1385    case ALT_CLK_CAN0:
1386    case ALT_CLK_CAN1:
1387    case ALT_CLK_GPIO_DB:
1388        ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1389            alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) :  ALT_CLK_PERIPHERAL_PLL_C4;
1390        break;
1391
1392    case ALT_CLK_H2F_USER1:
1393        ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1394            alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) :  ALT_CLK_PERIPHERAL_PLL_C5;
1395        break;
1396
1397    case ALT_CLK_SDMMC:
1398        temp = ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
1399        if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_F2S_PERIPH_REF_CLK)
1400        {
1401            ret = ALT_CLK_F2H_PERIPH_REF;
1402        }
1403        else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK)
1404        {
1405            ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1406                ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C4;
1407        }
1408        else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK)
1409        {
1410            ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1411                alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) :  ALT_CLK_PERIPHERAL_PLL_C3;
1412        }
1413        break;
1414
1415    case ALT_CLK_NAND_X:
1416    case ALT_CLK_NAND:
1417        temp = ALT_CLKMGR_PERPLL_SRC_NAND_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
1418        if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_F2S_PERIPH_REF_CLK)
1419        {
1420            ret = ALT_CLK_F2H_PERIPH_REF;
1421        }
1422        else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK)
1423        {
1424            ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1425                ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C4;
1426        }
1427        else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK)
1428        {
1429            ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1430                alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) :  ALT_CLK_PERIPHERAL_PLL_C3;
1431        }
1432        break;
1433
1434    case ALT_CLK_QSPI:
1435        temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
1436        if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_F2S_PERIPH_REF_CLK)
1437        {
1438            ret = ALT_CLK_F2H_PERIPH_REF;
1439        }
1440        else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
1441        {
1442            ret = (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE) ?
1443                ALT_CLK_IN_PIN_OSC1 : ALT_CLK_MAIN_PLL_C3;
1444        }
1445        else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
1446        {
1447            ret = (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE) ?
1448                alt_clk_pll_source_get(ALT_CLK_PERIPHERAL_PLL) :  ALT_CLK_PERIPHERAL_PLL_C2;
1449        }
1450        break;
1451
1452        // SDRAM Clock Group
1453    case ALT_CLK_SDRAM_PLL_C0:
1454    case ALT_CLK_SDRAM_PLL_C1:
1455    case ALT_CLK_SDRAM_PLL_C2:
1456    case ALT_CLK_SDRAM_PLL_C3:
1457    case ALT_CLK_SDRAM_PLL_C4:
1458    case ALT_CLK_SDRAM_PLL_C5:
1459        ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
1460            alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) :  ALT_CLK_SDRAM_PLL;
1461        break;
1462    case ALT_CLK_DDR_DQS:
1463        ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
1464            alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) :  ALT_CLK_SDRAM_PLL_C0;
1465        break;
1466    case ALT_CLK_DDR_2X_DQS:
1467        ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
1468            alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) :  ALT_CLK_SDRAM_PLL_C1;
1469        break;
1470    case ALT_CLK_DDR_DQ:
1471        ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
1472            alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) :  ALT_CLK_SDRAM_PLL_C2;
1473        break;
1474    case ALT_CLK_H2F_USER2:
1475        ret = (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE) ?
1476            alt_clk_pll_source_get(ALT_CLK_SDRAM_PLL) :  ALT_CLK_SDRAM_PLL_C5;
1477        break;
1478
1479        // Clock Output Pins
1480    case ALT_CLK_OUT_PIN_EMAC0_TX:
1481    case ALT_CLK_OUT_PIN_EMAC1_TX:
1482    case ALT_CLK_OUT_PIN_SDMMC:
1483    case ALT_CLK_OUT_PIN_I2C0_SCL:
1484    case ALT_CLK_OUT_PIN_I2C1_SCL:
1485    case ALT_CLK_OUT_PIN_I2C2_SCL:
1486    case ALT_CLK_OUT_PIN_I2C3_SCL:
1487    case ALT_CLK_OUT_PIN_SPIM0:
1488    case ALT_CLK_OUT_PIN_SPIM1:
1489    case ALT_CLK_OUT_PIN_QSPI:
1490        ret = ALT_CLK_UNKNOWN;
1491        break;
1492
1493    default:
1494        ret = ALT_CLK_UNKNOWN;
1495        break;
1496    }
1497
1498    return ret;
1499}
1500
1501//
1502// alt_clk_source_set() sets the specified clock's input reference clock source
1503// selection to the specified input. It does not handle gating the specified clock
1504// off and back on, those are covered in other functions in this API, but it does
1505// verify that the clock is off before changing the divider or PLL. Note that the PLL
1506// must have regained phase-lock before being the bypass is disabled.
1507//
1508ALT_STATUS_CODE alt_clk_source_set(ALT_CLK_t clk, ALT_CLK_t ref_clk)
1509{
1510    ALT_STATUS_CODE status = ALT_E_SUCCESS;
1511    uint32_t        temp;
1512
1513    if (ALT_CLK_MAIN_PLL == clk)
1514    {
1515        if ((ref_clk == ALT_CLK_IN_PIN_OSC1) || (ref_clk == ALT_CLK_OSC1))
1516        {
1517            // ret = ALT_E_SUCCESS;
1518        }
1519        else
1520        {
1521            status = ALT_E_BAD_ARG;
1522        }
1523    }
1524    else if (ALT_CLK_PERIPHERAL_PLL == clk)
1525    {
1526        // the PLL must be bypassed before getting here
1527        temp  = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
1528        temp &= ALT_CLKMGR_PERPLL_VCO_PSRC_CLR_MSK;
1529
1530        if ((ref_clk == ALT_CLK_IN_PIN_OSC1) || (ref_clk == ALT_CLK_OSC1))
1531        {
1532            temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1);
1533            alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
1534        }
1535        else if (ref_clk == ALT_CLK_IN_PIN_OSC2)
1536        {
1537            temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2);
1538            alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
1539        }
1540        else if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
1541        {
1542            temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF);
1543            alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
1544        }
1545        else
1546        {
1547            status = ALT_E_INV_OPTION;
1548        }
1549    }
1550    else if (ALT_CLK_SDRAM_PLL == clk)
1551    {
1552        temp  = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
1553        temp &= ALT_CLKMGR_SDRPLL_VCO_SSRC_CLR_MSK;
1554
1555        if ((ref_clk == ALT_CLK_IN_PIN_OSC1) || (ref_clk == ALT_CLK_OSC1))
1556        {
1557            temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1);
1558            alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
1559        }
1560        else if (ref_clk == ALT_CLK_IN_PIN_OSC2)
1561        {
1562            temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2);
1563            alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
1564        }
1565        else if (ref_clk == ALT_CLK_F2H_SDRAM_REF)
1566        {
1567            temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF);
1568            alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
1569        }
1570        else
1571        {
1572            status = ALT_E_INV_OPTION;
1573        }
1574    }
1575    else if ( ALT_CLK_L4_MP == clk)
1576    {
1577        // clock is gated off
1578        if (ref_clk == ALT_CLK_MAIN_PLL_C1)
1579        {
1580            alt_clrbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK);
1581        }
1582        else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C4)
1583        {
1584            alt_setbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK);
1585        }
1586        else
1587        {
1588            status = ALT_E_INV_OPTION;
1589        }
1590    }
1591    else if ( ALT_CLK_L4_SP == clk)
1592    {
1593        if (ref_clk == ALT_CLK_MAIN_PLL_C1)
1594        {
1595            alt_clrbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK);
1596        }
1597        else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C4)
1598        {
1599            alt_setbits_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK);
1600        }
1601        else
1602        {
1603            status = ALT_E_INV_OPTION;
1604        }
1605    }
1606    else if (ALT_CLK_SDMMC == clk)
1607    {
1608        temp  = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
1609        temp &= ALT_CLKMGR_PERPLL_SRC_SDMMC_CLR_MSK;
1610
1611        if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
1612        {
1613            temp |= ALT_CLKMGR_PERPLL_SRC_SDMMC_SET(ALT_CLKMGR_PERPLL_SRC_SDMMC_E_F2S_PERIPH_REF_CLK);
1614            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1615        }
1616        else if ((ref_clk == ALT_CLK_MAIN_PLL_C4) || (ref_clk == ALT_CLK_MAIN_NAND_SDMMC))
1617        {
1618            temp |= ALT_CLKMGR_PERPLL_SRC_SDMMC_SET(ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK);
1619            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1620        }
1621        else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C3)
1622        {
1623            temp |= ALT_CLKMGR_PERPLL_SRC_SDMMC_SET(ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK);
1624            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1625        }
1626        else
1627        {
1628            status = ALT_E_INV_OPTION;
1629        }
1630    }
1631    else if ((ALT_CLK_NAND_X == clk) || ( ALT_CLK_NAND == clk))
1632    {
1633        temp = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
1634        temp &= ALT_CLKMGR_PERPLL_SRC_NAND_CLR_MSK;
1635
1636        if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
1637        {
1638            temp |= ALT_CLKMGR_PERPLL_SRC_NAND_SET(ALT_CLKMGR_PERPLL_SRC_NAND_E_F2S_PERIPH_REF_CLK);
1639            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1640        }
1641        else if ((ref_clk == ALT_CLK_MAIN_PLL_C4) || (ref_clk == ALT_CLK_MAIN_NAND_SDMMC))
1642        {
1643            temp |= ALT_CLKMGR_PERPLL_SRC_NAND_SET(ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK);
1644            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1645        }
1646        else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C3)
1647        {
1648            temp |= ALT_CLKMGR_PERPLL_SRC_NAND_SET(ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK);
1649            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1650        }
1651        else
1652        {
1653            status = ALT_E_INV_OPTION;
1654        }
1655    }
1656    else if (ALT_CLK_QSPI == clk)
1657    {
1658        temp  = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
1659        temp &= ALT_CLKMGR_PERPLL_SRC_QSPI_CLR_MSK;
1660
1661        if (ref_clk == ALT_CLK_F2H_PERIPH_REF)
1662        {
1663            temp |= ALT_CLKMGR_PERPLL_SRC_QSPI_SET(ALT_CLKMGR_PERPLL_SRC_QSPI_E_F2S_PERIPH_REF_CLK);
1664            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1665        }
1666        else if ((ref_clk == ALT_CLK_MAIN_PLL_C3) || (ref_clk == ALT_CLK_MAIN_QSPI))
1667        {
1668            temp |= ALT_CLKMGR_PERPLL_SRC_QSPI_SET(ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK);
1669            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1670        }
1671        else if (ref_clk == ALT_CLK_PERIPHERAL_PLL_C2)
1672        {
1673            temp |= ALT_CLKMGR_PERPLL_SRC_QSPI_SET(ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK);
1674            alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, temp);
1675        }
1676        else
1677        {
1678            status = ALT_E_INV_OPTION;
1679        }
1680    }
1681
1682    return status;
1683}
1684
1685//
1686// alt_clk_ext_clk_freq_set() specifies the frequency of the external clock source as
1687// a measure of Hz. This value is stored in a static array and used for calculations.
1688// The supplied frequency should be within the Fmin and Fmax values allowed for the
1689// external clock source.
1690//
1691ALT_STATUS_CODE alt_clk_ext_clk_freq_set(ALT_CLK_t clk, alt_freq_t freq)
1692{
1693    ALT_STATUS_CODE status = ALT_E_BAD_ARG;
1694
1695    if ((clk == ALT_CLK_IN_PIN_OSC1) || (clk == ALT_CLK_OSC1))      // two names for one input
1696    {
1697        if ((freq >= alt_ext_clk_paramblok.clkosc1.freqmin) && (freq <= alt_ext_clk_paramblok.clkosc1.freqmax))
1698        {
1699            alt_ext_clk_paramblok.clkosc1.freqcur = freq;
1700            status = ALT_E_SUCCESS;
1701        }
1702        else
1703        {
1704            status = ALT_E_ARG_RANGE;
1705        }
1706    }
1707    else if (clk == ALT_CLK_IN_PIN_OSC2)                            // the other clock input pin
1708    {
1709        if ((freq >= alt_ext_clk_paramblok.clkosc2.freqmin) && (freq <= alt_ext_clk_paramblok.clkosc2.freqmax))
1710        {
1711            alt_ext_clk_paramblok.clkosc2.freqcur = freq;
1712            status = ALT_E_SUCCESS;
1713        }
1714        else
1715        {
1716            status = ALT_E_ARG_RANGE;
1717        }
1718    }
1719    else if (clk == ALT_CLK_F2H_PERIPH_REF)                         // clock from the FPGA
1720    {
1721        if ((freq >= alt_ext_clk_paramblok.periph.freqmin) && (freq <= alt_ext_clk_paramblok.periph.freqmax))
1722        {
1723            alt_ext_clk_paramblok.periph.freqcur = freq;
1724            status = ALT_E_SUCCESS;
1725        }
1726        else
1727        {
1728            status = ALT_E_ARG_RANGE;
1729        }
1730    }
1731    else if (clk == ALT_CLK_F2H_SDRAM_REF)                          // clock from the FPGA SDRAM
1732    {
1733        if ((freq >= alt_ext_clk_paramblok.sdram.freqmin) && (freq <= alt_ext_clk_paramblok.sdram.freqmax))
1734        {
1735            alt_ext_clk_paramblok.sdram.freqcur = freq;
1736            status = ALT_E_SUCCESS;
1737        }
1738        else
1739        {
1740            status = ALT_E_ARG_RANGE;
1741        }
1742    }
1743    else
1744    {
1745        status = ALT_E_BAD_ARG;
1746    }
1747
1748    return status;
1749}
1750
1751
1752//
1753// alt_clk_ext_clk_freq_get returns the frequency of the external clock source as
1754// a measure of Hz. This value is stored in a static array.
1755//
1756alt_freq_t alt_clk_ext_clk_freq_get(ALT_CLK_t clk)
1757{
1758    uint32_t ret = 0;
1759
1760    if ((clk == ALT_CLK_IN_PIN_OSC1) || (clk == ALT_CLK_OSC1))      // two names for one input
1761    {
1762        ret = alt_ext_clk_paramblok.clkosc1.freqcur;
1763    }
1764    else if (clk == ALT_CLK_IN_PIN_OSC2)
1765    {
1766        ret = alt_ext_clk_paramblok.clkosc2.freqcur;
1767    }
1768    else if (clk == ALT_CLK_F2H_PERIPH_REF)                         // clock from the FPGA
1769    {
1770        ret = alt_ext_clk_paramblok.periph.freqcur;
1771    }
1772    else if (clk == ALT_CLK_F2H_SDRAM_REF)                         // clock from the FPGA
1773    {
1774        ret = alt_ext_clk_paramblok.sdram.freqcur;
1775    }
1776    return ret;
1777}
1778
1779
1780//
1781// alt_clk_pll_cfg_get() returns the current PLL configuration.
1782//
1783ALT_STATUS_CODE alt_clk_pll_cfg_get(ALT_CLK_t pll, ALT_CLK_PLL_CFG_t * pll_cfg)
1784{
1785    ALT_STATUS_CODE        ret = ALT_E_ERROR;                  // return value
1786    uint32_t               temp;                               // temp variable
1787 
1788    if (pll_cfg == NULL)
1789    {
1790                ret = ALT_E_BAD_ARG;
1791                return ret;
1792    }
1793
1794    if (pll == ALT_CLK_MAIN_PLL)
1795    {
1796        temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
1797        pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC1;
1798        pll_cfg->mult = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp);
1799        pll_cfg->div = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp);
1800
1801        // Get the C0-C5 divider values:
1802        pll_cfg->cntrs[0] = ALT_CLKMGR_MAINPLL_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR));
1803        // C0 - mpu_clk
1804
1805        pll_cfg->cntrs[1] = ALT_CLKMGR_MAINPLL_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR));
1806        // C1 - main_clk
1807
1808        pll_cfg->cntrs[2] = ALT_CLKMGR_MAINPLL_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR));
1809        // C2 - dbg_base_clk
1810
1811        pll_cfg->cntrs[3] = ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR));
1812        // C3 - main_qspi_clk
1813
1814        pll_cfg->cntrs[4] = ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR));
1815        // C4 - main_nand_sdmmc_clk
1816
1817        pll_cfg->cntrs[5] = ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR));
1818        // C5 - cfg_s2f_user0_clk aka cfg_h2f_user0_clk
1819
1820        // The Main PLL C0-C5 outputs have no phase shift capabilities :
1821        pll_cfg->pshift[0] = pll_cfg->pshift[1] = pll_cfg->pshift[2] =
1822            pll_cfg->pshift[3] = pll_cfg->pshift[4] = pll_cfg->pshift[5] = 0;
1823        ret = ALT_E_SUCCESS;
1824    }
1825    else if (pll == ALT_CLK_PERIPHERAL_PLL)
1826    {
1827        temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR));
1828        if (temp <= 2)
1829        {
1830            if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
1831            {
1832                pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC1;
1833            }
1834            else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
1835            {
1836                pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC2;
1837            }
1838            else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
1839            {
1840                pll_cfg->ref_clk = ALT_CLK_F2H_PERIPH_REF;
1841            }
1842
1843            temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
1844            pll_cfg->mult = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp);
1845            pll_cfg->div = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp);
1846
1847            // Get the C0-C5 divider values:
1848            pll_cfg->cntrs[0] = ALT_CLKMGR_PERPLL_EMAC0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR));
1849            // C0 - emac0_clk
1850
1851            pll_cfg->cntrs[1] = ALT_CLKMGR_PERPLL_EMAC1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR));
1852            // C1 - emac1_clk
1853
1854            pll_cfg->cntrs[2] = ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR));
1855            // C2 - periph_qspi_clk
1856
1857            pll_cfg->cntrs[3] = ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR));
1858            // C3 - periph_nand_sdmmc_clk
1859
1860            pll_cfg->cntrs[4] = ALT_CLKMGR_PERPLL_PERBASECLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR));
1861            // C4 - periph_base_clk
1862
1863            pll_cfg->cntrs[5] = ALT_CLKMGR_PERPLL_S2FUSER1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR));
1864            // C5 - s2f_user1_clk
1865
1866            // The Peripheral PLL C0-C5 outputs have no phase shift capabilities :
1867            pll_cfg->pshift[0] = pll_cfg->pshift[1] = pll_cfg->pshift[2] =
1868                pll_cfg->pshift[3] = pll_cfg->pshift[4] = pll_cfg->pshift[5] = 0;
1869            ret = ALT_E_SUCCESS;
1870        }
1871    }
1872    else if (pll == ALT_CLK_SDRAM_PLL)
1873    {
1874        temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
1875        if (temp <= 2)
1876        {
1877            if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
1878            {
1879                pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC1;
1880            }
1881            else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
1882            {
1883                pll_cfg->ref_clk = ALT_CLK_IN_PIN_OSC2;
1884            }
1885            else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
1886            {
1887                pll_cfg->ref_clk = ALT_CLK_F2H_SDRAM_REF;
1888            }
1889
1890            pll_cfg->mult = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
1891            pll_cfg->div = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
1892
1893            // Get the C0-C5 divider values:
1894            pll_cfg->cntrs[0]  = ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR));
1895            pll_cfg->pshift[0] = ALT_CLKMGR_SDRPLL_DDRDQSCLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR));
1896            // C0  - ddr_dqs_clk
1897
1898            pll_cfg->cntrs[1]  = ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR));
1899            pll_cfg->pshift[1] = ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR));
1900            // C1  - ddr_2x_dqs_clk
1901
1902            pll_cfg->cntrs[2]  = ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR));
1903            pll_cfg->pshift[2] = ALT_CLKMGR_SDRPLL_DDRDQCLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR));
1904            // C2  - ddr_dq_clk
1905
1906            pll_cfg->cntrs[3]  = pll_cfg->cntrs[4] = pll_cfg->pshift[3] = pll_cfg->pshift[4] = 0;
1907            // C3  & C4 outputs don't exist on the SDRAM PLL
1908
1909            pll_cfg->cntrs[5]  = ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR));
1910            pll_cfg->pshift[5] = ALT_CLKMGR_SDRPLL_S2FUSER2CLK_PHASE_GET(alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR));
1911            // C5  - s2f_user2_clk or h2f_user2_clk
1912
1913            ret = ALT_E_SUCCESS;
1914        }
1915    }
1916
1917    return ret;
1918}
1919
1920
1921//
1922// alt_clk_pll_cfg_set() sets the PLL configuration using the configuration parameters
1923// specified in pll_cfg.
1924//
1925ALT_STATUS_CODE alt_clk_pll_cfg_set(ALT_CLK_t pll, const ALT_CLK_PLL_CFG_t * pll_cfg)
1926{
1927    if (pll_cfg == NULL)
1928    {
1929                return ALT_E_BAD_ARG;
1930    }
1931
1932    if (alt_clk_pll_is_bypassed(pll) != ALT_E_TRUE)         // safe to write the PLL registers?
1933    {
1934        return ALT_E_ERROR;
1935    }
1936
1937    ALT_STATUS_CODE ret = ALT_E_ERROR;
1938    uint32_t        temp;
1939
1940    if (pll == ALT_CLK_MAIN_PLL)
1941    {
1942        temp  = (ALT_CLKMGR_MAINPLL_VCO_NUMER_CLR_MSK & ALT_CLKMGR_MAINPLL_VCO_DENOM_CLR_MSK)
1943            & alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
1944        temp |= ALT_CLKMGR_MAINPLL_VCO_NUMER_SET(pll_cfg->mult) |
1945            ALT_CLKMGR_MAINPLL_VCO_DENOM_SET(pll_cfg->div);
1946
1947        alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, temp);
1948        alt_write_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR,           pll_cfg->cntrs[0]);
1949        alt_write_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR,          pll_cfg->cntrs[1]);
1950        alt_write_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR,         pll_cfg->cntrs[2]);
1951        alt_write_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR,      pll_cfg->cntrs[3]);
1952        alt_write_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR, pll_cfg->cntrs[4]);
1953        alt_write_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR,   pll_cfg->cntrs[5]);
1954        ret = ALT_E_SUCCESS;
1955    }
1956    else if (pll == ALT_CLK_PERIPHERAL_PLL)
1957    {
1958        temp =  ALT_CLKMGR_PERPLL_VCO_NUMER_CLR_MSK & ALT_CLKMGR_PERPLL_VCO_DENOM_CLR_MSK
1959            & ALT_CLKMGR_PERPLL_VCO_PSRC_CLR_MSK;
1960        temp &= alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
1961        temp |= ALT_CLKMGR_PERPLL_VCO_NUMER_SET(pll_cfg->mult)
1962            | ALT_CLKMGR_PERPLL_VCO_DENOM_SET(pll_cfg->div);
1963
1964        if ((pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC1) || (pll_cfg->ref_clk == ALT_CLK_OSC1))
1965        {
1966            temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1);
1967        }
1968        else if (pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC2)
1969        {
1970            temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2);
1971        }
1972        else if (pll_cfg->ref_clk == ALT_CLK_F2H_PERIPH_REF)
1973        {
1974            temp |= ALT_CLKMGR_PERPLL_VCO_PSRC_SET(ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF);
1975        }
1976        else
1977        {
1978            return ret;
1979        }
1980
1981        alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, temp);
1982        alt_write_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR,        pll_cfg->cntrs[0]);
1983        alt_write_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR,        pll_cfg->cntrs[1]);
1984        alt_write_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR,      pll_cfg->cntrs[2]);
1985        alt_write_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, pll_cfg->cntrs[3]);
1986        alt_write_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR,      pll_cfg->cntrs[4]);
1987        alt_write_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR,     pll_cfg->cntrs[5]);
1988        ret = ALT_E_SUCCESS;
1989    }
1990    else if (pll == ALT_CLK_SDRAM_PLL)
1991    {
1992        // write the SDRAM PLL VCO Counter -----------------------------
1993        temp =  ALT_CLKMGR_SDRPLL_VCO_NUMER_CLR_MSK & ALT_CLKMGR_SDRPLL_VCO_DENOM_CLR_MSK
1994            & ALT_CLKMGR_SDRPLL_VCO_SSRC_CLR_MSK;           // make a mask
1995        temp &= alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
1996        temp |= ALT_CLKMGR_SDRPLL_VCO_NUMER_SET(pll_cfg->mult)
1997            | ALT_CLKMGR_SDRPLL_VCO_DENOM_SET(pll_cfg->div)
1998            | ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_SET_MSK;
1999        // setting this bit aligns the output phase of the counters and prevents
2000        // glitches and too-short clock periods when restarting.
2001        // this bit is cleared at the end of this routine
2002
2003        if ((pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC1) || (pll_cfg->ref_clk == ALT_CLK_OSC1))
2004        {
2005            temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1);
2006        }
2007        else if (pll_cfg->ref_clk == ALT_CLK_IN_PIN_OSC2)
2008        {
2009            temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2);
2010        }
2011        else if (pll_cfg->ref_clk == ALT_CLK_F2H_PERIPH_REF)
2012        {
2013            temp |= ALT_CLKMGR_SDRPLL_VCO_SSRC_SET(ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF);
2014        }
2015        else
2016        {
2017            return ret;
2018        }
2019
2020        alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, temp);
2021
2022        // write the SDRAM PLL C0 Divide Counter -----------------------------
2023        temp =  ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_SET(pll_cfg->cntrs[0])
2024            | ALT_CLKMGR_SDRPLL_DDRDQSCLK_PHASE_SET(pll_cfg->pshift[0]);
2025
2026        alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
2027                                 ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR, temp,
2028                                 ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_DDRDQSCLK_PHASE_SET_MSK,
2029                                 ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_LSB);
2030
2031        // write the SDRAM PLL C1 Divide Counter -----------------------------
2032        if (ret == ALT_E_SUCCESS)
2033        {
2034            temp =  ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_SET(pll_cfg->cntrs[1])
2035                | ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_PHASE_SET(pll_cfg->pshift[1]);
2036            alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
2037                                     ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR, temp,
2038                                     ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_PHASE_SET_MSK,
2039                                     ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_LSB);
2040        }
2041
2042        // write the SDRAM PLL C2 Divide Counter -----------------------------
2043        if (ret == ALT_E_SUCCESS)
2044        {
2045            temp =  ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_SET(pll_cfg->cntrs[2])
2046                | ALT_CLKMGR_SDRPLL_DDRDQCLK_PHASE_SET(pll_cfg->pshift[2]);
2047            alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
2048                                     ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR, temp,
2049                                     ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_DDRDQCLK_PHASE_SET_MSK,
2050                                     ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_LSB);
2051        }
2052
2053        // write the SDRAM PLL C5 Divide Counter -----------------------------
2054        if (ret == ALT_E_SUCCESS)
2055        {
2056            temp =  ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_SET(pll_cfg->cntrs[2])
2057                | ALT_CLKMGR_SDRPLL_S2FUSER2CLK_PHASE_SET(pll_cfg->pshift[2]);
2058            alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_STAT_ADDR,
2059                                     ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR, temp,
2060                                     ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_SET_MSK | ALT_CLKMGR_SDRPLL_S2FUSER2CLK_PHASE_SET_MSK,
2061                                     ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_LSB);
2062        }
2063
2064        if (ret == ALT_E_SUCCESS)
2065        {
2066            alt_clrbits_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_SET_MSK);
2067            // allow the phase multiplexer and output counter to leave reset
2068        }
2069    }
2070
2071    return ret;
2072}
2073
2074
2075//
2076// alt_clk_pll_vco_cfg_get() returns the current PLL VCO frequency configuration.
2077//
2078ALT_STATUS_CODE alt_clk_pll_vco_cfg_get(ALT_CLK_t pll, uint32_t * mult, uint32_t * div)
2079{
2080    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2081    uint32_t        temp;
2082
2083    if ( (mult == NULL) || (div == NULL) )
2084    {
2085                return ALT_E_BAD_ARG;
2086    }
2087
2088    if (pll == ALT_CLK_MAIN_PLL)
2089    {
2090        temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
2091        *mult = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp) + 1;
2092        *div  = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp) + 1;
2093    }
2094    else if (pll == ALT_CLK_PERIPHERAL_PLL)
2095    {
2096        temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
2097        *mult = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp) + 1;
2098        *div  = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp) + 1;
2099    }
2100    else if (pll == ALT_CLK_SDRAM_PLL)
2101    {
2102        temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
2103        *mult = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(temp) + 1;
2104        *div  = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(temp) + 1;
2105    }
2106    else
2107    {
2108        status = ALT_E_ERROR;
2109    }
2110
2111    return status;
2112}
2113
2114
2115/****************************************************************************************/
2116/* This enum enumerates a set of possible change methods that are available for use by  */
2117/* alt_clk_pll_vco_cfg_set() to change VCO parameter settings.                          */
2118/****************************************************************************************/
2119
2120typedef enum ALT_CLK_PLL_VCO_CHG_METHOD_e
2121{
2122    ALT_VCO_CHG_NONE_VALID      = 0,            /*  No valid method to  change PLL
2123                                                 *  VCO was found                       */
2124    ALT_VCO_CHG_NOCHANGE        = 0x00000001,   /*  Proposed new VCO values are the
2125                                                 *  same as the old values              */
2126    ALT_VCO_CHG_NUM             = 0x00000002,   /*  Can change the VCO multiplier
2127                                                 *  alone                               */
2128    ALT_VCO_CHG_NUM_BYP         = 0x00000004,   /*  A VCO multiplier-only change will
2129                                                 *  require putting the PLL in bypass   */
2130    ALT_VCO_CHG_DENOM           = 0x00000008,   /*  Can change the VCO divider
2131                                                 *  alone                               */
2132    ALT_VCO_CHG_DENOM_BYP       = 0x00000010,   /*  A VCO divider-only change will
2133                                                 *  require putting the PLL in bypass   */
2134    ALT_VCO_CHG_NUM_DENOM       = 0x00000020,   /*  Can change the clock multiplier
2135                                                 *  first. then the clock divider       */
2136    ALT_VCO_CHG_NUM_DENOM_BYP   = 0x00000040,   /*  Changing the clock multiplier first.
2137                                                 *  then the clock divider will
2138                                                 *  require putting the PLL in bypass   */
2139    ALT_VCO_CHG_DENOM_NUM       = 0x00000080,   /*  Can change the clock divider first.
2140                                                 *  then the clock multiplier           */
2141    ALT_VCO_CHG_DENOM_NUM_BYP   = 0x00000100    /*  Changing the clock divider first.
2142                                                 *  then the clock multiplier will
2143                                                 *  require putting the PLL in bypass   */
2144} ALT_CLK_PLL_VCO_CHG_METHOD_t;
2145
2146
2147
2148/****************************************************************************************/
2149/* alt_clk_pll_vco_chg_methods_get() determines which possible methods to change the    */
2150/* VCO are allowed within the limits set by the maximum PLL multiplier and divider      */
2151/* values and by the upper and lower frequency limits of the PLL, and also determines   */
2152/* whether each of these changes can be made without the PLL losing lock, which         */
2153/* requires the PLL to be bypassed before making changes, and removed from bypass state */
2154/* afterwards.                                                                          */
2155/****************************************************************************************/
2156
2157
2158#define ALT_CLK_PLL_VCO_CHG_METHOD_TEST_MODE        false
2159    // used for testing writes to the PLL VCOs
2160
2161
2162
2163static ALT_CLK_PLL_VCO_CHG_METHOD_t alt_clk_pll_vco_chg_methods_get(ALT_CLK_t pll,
2164        uint32_t mult, uint32_t div )
2165{
2166#if ALT_CLK_PLL_VCO_CHG_METHOD_TEST_MODE
2167
2168    // used for testing
2169    return ALT_VCO_CHG_NOCHANGE;
2170
2171#else
2172
2173    // check PLL max value limits
2174    if (   (mult == 0) || (mult > ALT_CLK_PLL_MULT_MAX)
2175        || (div  == 0) || (div  > ALT_CLK_PLL_DIV_MAX)
2176       )
2177    {
2178        return ALT_VCO_CHG_NONE_VALID;
2179    }
2180
2181    ALT_CLK_PLL_VCO_CHG_METHOD_t    ret = ALT_VCO_CHG_NONE_VALID;
2182    uint32_t                        temp;
2183    uint32_t                        numer;
2184    uint32_t                        denom;
2185    uint32_t                        freqmax;
2186    uint32_t                        freqmin;
2187    uint32_t                        inputfreq;
2188    uint32_t                        guardband;
2189    bool                            numerchg = false;
2190    bool                            denomchg = false;
2191    bool                            within_gb;
2192
2193    // gather data values according to PLL
2194    if (pll == ALT_CLK_MAIN_PLL)
2195    {
2196        temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
2197
2198        numer = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp);
2199        denom = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp);
2200
2201        freqmax   = alt_pll_clk_paramblok.MainPLL_800.freqmax;
2202        freqmin   = alt_pll_clk_paramblok.MainPLL_800.freqmin;
2203        guardband = alt_pll_clk_paramblok.MainPLL_800.guardband;
2204
2205        inputfreq = alt_ext_clk_paramblok.clkosc1.freqcur;
2206    }
2207
2208    else if (pll == ALT_CLK_PERIPHERAL_PLL)
2209    {
2210        temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
2211
2212        numer = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp);
2213        denom = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp);
2214
2215        freqmax   = alt_pll_clk_paramblok.PeriphPLL_800.freqmax;
2216        freqmin   = alt_pll_clk_paramblok.PeriphPLL_800.freqmin;
2217        guardband = alt_pll_clk_paramblok.PeriphPLL_800.guardband;
2218
2219        temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(temp);
2220        if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
2221        {
2222            inputfreq = alt_ext_clk_paramblok.clkosc1.freqcur;
2223        }
2224        else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
2225        {
2226            inputfreq = alt_ext_clk_paramblok.clkosc2.freqcur;
2227        }
2228        else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
2229        {
2230            inputfreq = alt_ext_clk_paramblok.periph.freqcur;
2231        }
2232        else
2233        {
2234            return ret;
2235        }
2236    }
2237
2238    else if (pll == ALT_CLK_SDRAM_PLL)
2239    {
2240        temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
2241
2242        numer = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(temp);
2243        denom = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(temp);
2244
2245        freqmax   = alt_pll_clk_paramblok.SDRAMPLL_800.freqmax;
2246        freqmin   = alt_pll_clk_paramblok.SDRAMPLL_800.freqmin;
2247        guardband = alt_pll_clk_paramblok.SDRAMPLL_800.guardband;
2248
2249        temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(temp);
2250        if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
2251        {
2252            inputfreq = alt_ext_clk_paramblok.clkosc1.freqcur;
2253        }
2254        else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
2255        {
2256            inputfreq = alt_ext_clk_paramblok.clkosc2.freqcur;
2257        }
2258        else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
2259        {
2260            inputfreq = alt_ext_clk_paramblok.sdram.freqcur;
2261        }
2262        else
2263        {
2264            return ret;
2265        }
2266    }
2267    else
2268    {
2269        return ret;
2270    }
2271
2272    temp = mult * (inputfreq / div);
2273    if ((temp <= freqmax) && (temp >= freqmin))     // are the final values within frequency limits?
2274    {
2275        numer++;
2276        denom++;
2277        numerchg = (mult != numer);
2278        denomchg = (div != denom);
2279
2280        if (!numerchg && !denomchg)
2281        {
2282            ret = ALT_VCO_CHG_NOCHANGE;
2283        }
2284        else if (numerchg && !denomchg)
2285        {
2286            within_gb = alt_within_delta(numer, mult, guardband);
2287            // check if change is within the guardband limits
2288            temp = mult * (inputfreq / denom);
2289            if ((temp <= freqmax) && (temp >= freqmin))
2290            {
2291                ret = ALT_VCO_CHG_NUM;
2292                if (!within_gb) ret |= ALT_VCO_CHG_NUM_BYP;
2293            }
2294        }
2295        else if (!numerchg && denomchg)
2296        {
2297            within_gb = alt_within_delta(denom, div, guardband);
2298            temp = numer * (inputfreq / div);
2299            if ((temp <= freqmax) && (temp >= freqmin))
2300            {
2301                ret = ALT_VCO_CHG_DENOM;
2302                if (!within_gb)
2303                {
2304                    ret |= ALT_VCO_CHG_DENOM_BYP;
2305                }
2306            }
2307        }
2308        else    //numerchg && denomchg
2309        {
2310            within_gb = alt_within_delta(numer, mult, guardband);
2311            temp = mult * (inputfreq / denom);
2312            if ((temp <= freqmax) && (temp >= freqmin))
2313            {
2314                ret = ALT_VCO_CHG_NUM_DENOM;
2315                if (!within_gb)
2316                {
2317                    ret |= ALT_VCO_CHG_NUM_DENOM_BYP;
2318                }
2319            }
2320            within_gb = alt_within_delta(denom, div, guardband);
2321            temp = numer * (inputfreq / div);
2322            if ((temp <= freqmax) && (temp >= freqmin))
2323            {
2324                ret = ALT_VCO_CHG_DENOM_NUM;
2325                if (!within_gb)
2326                {
2327                    ret |= ALT_VCO_CHG_DENOM_NUM_BYP;
2328                }
2329            }
2330        }
2331    }
2332
2333    return ret;
2334#endif
2335}
2336
2337
2338/****************************************************************************************/
2339/* alt_clk_pll_vco_cfg_set() sets the PLL VCO frequency configuration using the         */
2340/* supplied multiplier and divider arguments. alt_clk_pll_vco_chg_methods_get()         */
2341/* determines which methods are allowed by the limits set by the maximum multiplier     */
2342/* and divider values and by the upper and lower frequency limits of the PLL, and also  */
2343/* determines whether these changes can be made without requiring the PLL to be         */
2344/* bypassed. alt_clk_pll_vco_cfg_set() then carries out the actions required to effect  */
2345/* the method chosen to change the VCO settings.                                        */
2346/****************************************************************************************/
2347
2348ALT_STATUS_CODE alt_clk_pll_vco_cfg_set(ALT_CLK_t pll, uint32_t mult, uint32_t div)
2349{
2350    ALT_STATUS_CODE                 ret = ALT_E_ERROR;
2351    ALT_CLK_PLL_VCO_CHG_METHOD_t    method;
2352    bool                            byp = false;
2353    void                            *vaddr;
2354    uint32_t                        numermask, denommask;
2355    uint32_t                        numershift, denomshift;
2356
2357
2358    method = alt_clk_pll_vco_chg_methods_get(pll, mult, div);
2359
2360    if (method == ALT_VCO_CHG_NONE_VALID)
2361    {
2362        ret = ALT_E_BAD_CLK;
2363    }
2364    else if (method == ALT_VCO_CHG_NOCHANGE)
2365    {
2366        ret = ALT_E_INV_OPTION;
2367    }
2368    else
2369    {
2370        if (pll == ALT_CLK_MAIN_PLL)
2371        {
2372            vaddr = ALT_CLKMGR_MAINPLL_VCO_ADDR;
2373            numermask = ALT_CLKMGR_MAINPLL_VCO_NUMER_SET_MSK;
2374            denommask = ALT_CLKMGR_MAINPLL_VCO_DENOM_SET_MSK;
2375            numershift = ALT_CLKMGR_MAINPLL_VCO_NUMER_LSB;
2376            denomshift = ALT_CLKMGR_MAINPLL_VCO_DENOM_LSB;
2377        }
2378        else if (pll == ALT_CLK_PERIPHERAL_PLL)
2379        {
2380            vaddr = ALT_CLKMGR_PERPLL_VCO_ADDR;
2381            numermask = ALT_CLKMGR_PERPLL_VCO_NUMER_SET_MSK;
2382            denommask = ALT_CLKMGR_PERPLL_VCO_DENOM_SET_MSK;
2383            numershift = ALT_CLKMGR_PERPLL_VCO_NUMER_LSB;
2384            denomshift = ALT_CLKMGR_PERPLL_VCO_DENOM_LSB;
2385        }
2386        else if (pll == ALT_CLK_SDRAM_PLL)
2387        {
2388            vaddr = ALT_CLKMGR_SDRPLL_VCO_ADDR;
2389            numermask = ALT_CLKMGR_SDRPLL_VCO_NUMER_SET_MSK;
2390            denommask = ALT_CLKMGR_SDRPLL_VCO_DENOM_SET_MSK;
2391            numershift = ALT_CLKMGR_SDRPLL_VCO_NUMER_LSB;
2392            denomshift = ALT_CLKMGR_SDRPLL_VCO_DENOM_LSB;
2393        }
2394        else { return ALT_E_BAD_ARG; }
2395
2396        mult--;
2397        div--;
2398
2399        if (method & ALT_VCO_CHG_NUM)
2400        {
2401            if (method & ALT_VCO_CHG_NUM_BYP)
2402            {
2403                alt_clk_pll_bypass_enable(pll, 0);
2404                byp = true;
2405                alt_clk_mgr_wait(vaddr, ALT_SW_MANAGED_CLK_WAIT_BYPASS);
2406            }
2407            alt_replbits_word(vaddr, numermask, mult << numershift);
2408        }
2409
2410        else if (method & ALT_VCO_CHG_DENOM)
2411        {
2412            if (method & ALT_VCO_CHG_DENOM_BYP)
2413            {
2414                alt_clk_pll_bypass_enable(pll, 0);
2415                byp = true;
2416            }
2417            alt_replbits_word(vaddr, denommask, div << denomshift);
2418        }
2419
2420        else if (method & ALT_VCO_CHG_NUM_DENOM)
2421        {
2422            if (method & ALT_VCO_CHG_NUM_DENOM_BYP)
2423            {
2424                alt_clk_pll_bypass_enable(pll, 0);
2425                byp = true;
2426            }
2427            alt_replbits_word(vaddr, numermask, mult << numershift);
2428            if (!byp)       // if PLL is not bypassed
2429            {
2430                ret = alt_clk_pll_lock_wait(ALT_CLK_MAIN_PLL, 1000);
2431                      // verify PLL is still locked or wait for it to lock again
2432            }
2433            alt_replbits_word(vaddr, denommask, div << denomshift);
2434        }
2435
2436        else if (method & ALT_VCO_CHG_DENOM_NUM)
2437        {
2438            if (method & ALT_VCO_CHG_DENOM_NUM_BYP)
2439            {
2440                alt_clk_pll_bypass_enable(pll, 0);
2441                byp = true;
2442            }
2443            alt_replbits_word(vaddr, numermask, mult << numershift);
2444            if (!byp)       // if PLL is not bypassed
2445            {
2446                ret = alt_clk_pll_lock_wait(ALT_CLK_MAIN_PLL, 1000);
2447                      // verify PLL is still locked or wait for it to lock again
2448            }
2449            alt_replbits_word(vaddr, denommask, div << denomshift);
2450        }
2451
2452        ret = alt_clk_pll_lock_wait(ALT_CLK_MAIN_PLL, 1000);
2453              // verify PLL is still locked or wait for it to lock again
2454        if (byp)
2455        {
2456            alt_clk_pll_bypass_disable(pll);
2457            alt_clk_mgr_wait(vaddr, ALT_SW_MANAGED_CLK_WAIT_BYPASS);
2458                // wait for PLL to come out of bypass mode completely
2459        }
2460    }
2461    return ret;
2462}
2463
2464
2465//
2466// alt_clk_pll_vco_freq_get() gets the VCO frequency of the specified PLL.
2467// Note that since there is at present no known way for software to obtain the speed
2468// bin of the SoC or MPU that it is running on, the function below only deals with the
2469// 800 MHz part. This may need to be revised in the future.
2470//
2471ALT_STATUS_CODE alt_clk_pll_vco_freq_get(ALT_CLK_t pll, alt_freq_t * freq)
2472{
2473    uint64_t            temp1 = 0;
2474    uint32_t            temp;
2475    uint32_t            numer;
2476    uint32_t            denom;
2477    ALT_STATUS_CODE     ret = ALT_E_BAD_ARG;
2478
2479    if (freq == NULL)
2480    {
2481                return ret;
2482    }
2483
2484    if (pll == ALT_CLK_MAIN_PLL)
2485    {
2486        temp = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
2487        numer = ALT_CLKMGR_MAINPLL_VCO_NUMER_GET(temp);
2488        denom = ALT_CLKMGR_MAINPLL_VCO_DENOM_GET(temp);
2489        temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc1.freqcur;
2490        temp1 *= (numer + 1);
2491        temp1 /= (denom + 1);
2492
2493        if (temp1 <= UINT32_MAX)
2494        {
2495            temp = (alt_freq_t) temp1;
2496            alt_pll_clk_paramblok.MainPLL_800.freqcur = temp;
2497            // store this value in the parameter block table
2498             *freq = temp;
2499            // should NOT check value against PLL frequency limits
2500            ret = ALT_E_SUCCESS;
2501        }
2502        else
2503        {
2504            ret = ALT_E_ERROR;
2505        }
2506    }
2507    else if (pll == ALT_CLK_PERIPHERAL_PLL)
2508    {
2509        temp = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
2510        numer = ALT_CLKMGR_PERPLL_VCO_NUMER_GET(temp);
2511        denom = ALT_CLKMGR_PERPLL_VCO_DENOM_GET(temp);
2512        temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(temp);
2513        if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
2514        {
2515            temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc1.freqcur;
2516        }
2517        else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
2518        {
2519            temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc2.freqcur;
2520        }
2521        else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
2522        {
2523            temp1 = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
2524        }
2525
2526        if (temp1 != 0)
2527        {
2528            temp1 *= (numer + 1);
2529            temp1 /= (denom + 1);
2530            if (temp1 <= UINT32_MAX)
2531            {
2532                temp = (alt_freq_t) temp1;
2533                alt_pll_clk_paramblok.PeriphPLL_800.freqcur = temp;
2534                // store this value in the parameter block table
2535
2536                *freq = temp;
2537                ret = ALT_E_SUCCESS;
2538            }
2539            else
2540            {
2541                ret = ALT_E_ERROR;
2542            }
2543        }       // this returns ALT_BAD_ARG if the source isn't known
2544    }
2545    else if (pll == ALT_CLK_SDRAM_PLL)
2546    {
2547        temp = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
2548        numer = ALT_CLKMGR_SDRPLL_VCO_NUMER_GET(temp);
2549        denom = ALT_CLKMGR_SDRPLL_VCO_DENOM_GET(temp);
2550        temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(temp);
2551        if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
2552        {
2553            temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc1.freqcur;
2554        }
2555        else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
2556        {
2557            temp1 = (uint64_t) alt_ext_clk_paramblok.clkosc2.freqcur;
2558        }
2559        else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
2560        {
2561            temp1 = (uint64_t) alt_ext_clk_paramblok.sdram.freqcur;
2562        }
2563
2564        if (temp1 != 0)
2565        {
2566            temp1 *= (numer + 1);
2567            temp1 /= (denom + 1);
2568            if (temp1 <= UINT32_MAX)
2569            {
2570                temp = (alt_freq_t) temp1;
2571                alt_pll_clk_paramblok.SDRAMPLL_800.freqcur = temp;
2572                // store this value in the parameter block table
2573
2574                *freq = temp;
2575                ret = ALT_E_SUCCESS;
2576            }
2577            else
2578            {
2579                ret = ALT_E_ERROR;
2580            }
2581        }
2582    }       // which returns ALT_BAD_ARG if the source isn't known
2583
2584    return ret;
2585}
2586
2587//
2588// Returns the current guard band range in effect for the PLL.
2589//
2590uint32_t alt_clk_pll_guard_band_get(ALT_CLK_t pll)
2591{
2592    uint32_t ret = 0;
2593
2594    if (pll == ALT_CLK_MAIN_PLL)
2595    {
2596        ret = alt_pll_clk_paramblok.MainPLL_800.guardband;
2597    }
2598    else if (pll == ALT_CLK_PERIPHERAL_PLL)
2599    {
2600        ret = alt_pll_clk_paramblok.PeriphPLL_800.guardband;
2601    }
2602    else if (pll == ALT_CLK_SDRAM_PLL)
2603    {
2604        ret = alt_pll_clk_paramblok.SDRAMPLL_800.guardband;
2605    }
2606    return ret;
2607}
2608
2609//
2610// clk_mgr_pll_guard_band_set() changes the guard band from its current value to permit
2611// a more lenient or stringent policy to be in effect for the implementation of the
2612// functions configuring PLL VCO frequency.
2613//
2614ALT_STATUS_CODE alt_clk_pll_guard_band_set(ALT_CLK_t pll, uint32_t guard_band)
2615{
2616    if (   (guard_band > UINT12_MAX) || (guard_band <= 0)
2617        || (guard_band > ALT_GUARDBAND_LIMIT)
2618       )
2619    {
2620        return ALT_E_ARG_RANGE;
2621    }
2622
2623    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2624
2625    if (pll == ALT_CLK_MAIN_PLL)
2626    {
2627        alt_pll_clk_paramblok.MainPLL_800.guardband = guard_band;
2628        //alt_pll_clk_paramblok.MainPLL_600.guardband = guard_band;
2629        // ??? Don't know how to check the MPU speed bin yet, so only 800 MHz struct is used
2630    }
2631    else if (pll == ALT_CLK_PERIPHERAL_PLL)
2632    {
2633        alt_pll_clk_paramblok.PeriphPLL_800.guardband = guard_band;
2634        //alt_pll_clk_paramblok.PeriphPLL_600.guardband = guard_band;
2635    }
2636    else if (pll == ALT_CLK_SDRAM_PLL)
2637    {
2638        alt_pll_clk_paramblok.SDRAMPLL_800.guardband = guard_band;
2639        //alt_pll_clk_paramblok.SDRAMPLL_600.guardband = guard_band;
2640    }
2641    else
2642    {
2643        status = ALT_E_ERROR;
2644    }
2645
2646    return status;
2647}
2648
2649//
2650// alt_clk_divider_get() gets configured divider value for the specified clock.
2651//
2652ALT_STATUS_CODE alt_clk_divider_get(ALT_CLK_t clk, uint32_t * div)
2653{
2654    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2655    uint32_t        temp;
2656
2657    if (div == NULL)
2658    {
2659                return ALT_E_BAD_ARG;
2660    }
2661
2662    switch (clk)
2663    {
2664        // Main PLL outputs
2665    case ALT_CLK_MAIN_PLL_C0:
2666    case ALT_CLK_MPU:
2667        *div = (ALT_CLKMGR_MAINPLL_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR)) + 1) *
2668               (ALT_CLKMGR_ALTERA_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR)) + 1);
2669        break;
2670
2671    case ALT_CLK_MAIN_PLL_C1:
2672    case ALT_CLK_L4_MAIN:
2673    case ALT_CLK_L3_MAIN:
2674        *div = (ALT_CLKMGR_MAINPLL_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR)) + 1) *
2675               (ALT_CLKMGR_ALTERA_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR)) + 1);
2676        break;
2677
2678    case ALT_CLK_MAIN_PLL_C2:
2679    case ALT_CLK_DBG_BASE:
2680    case ALT_CLK_DBG_TIMER:
2681        *div = (ALT_CLKMGR_MAINPLL_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR)) + 1) *
2682               (ALT_CLKMGR_ALTERA_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_DBGATCLK_ADDR)) + 1);
2683        break;
2684
2685    case ALT_CLK_MAIN_PLL_C3:
2686    case ALT_CLK_MAIN_QSPI:
2687        *div = (ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR))) + 1;
2688        break;
2689
2690    case ALT_CLK_MAIN_PLL_C4:
2691    case ALT_CLK_MAIN_NAND_SDMMC:
2692        *div = (ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR))) + 1;
2693        break;
2694
2695    case ALT_CLK_MAIN_PLL_C5:
2696    case ALT_CLK_CFG:
2697    case ALT_CLK_H2F_USER0:
2698        *div = (ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR))) + 1;
2699        break;
2700
2701        /////
2702
2703        // Peripheral PLL outputs
2704    case ALT_CLK_PERIPHERAL_PLL_C0:
2705    case ALT_CLK_EMAC0:
2706        *div = (ALT_CLKMGR_PERPLL_EMAC0CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR))) + 1;
2707        break;
2708
2709    case ALT_CLK_PERIPHERAL_PLL_C1:
2710    case ALT_CLK_EMAC1:
2711        *div = (ALT_CLKMGR_PERPLL_EMAC1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR))) + 1;
2712        break;
2713
2714    case ALT_CLK_PERIPHERAL_PLL_C2:
2715        *div = (ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR))) + 1;
2716        break;
2717
2718    case ALT_CLK_PERIPHERAL_PLL_C3:
2719        *div = (ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR))) + 1;
2720        break;
2721
2722    case ALT_CLK_PERIPHERAL_PLL_C4:
2723        *div = (ALT_CLKMGR_PERPLL_PERBASECLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR))) + 1;
2724        break;
2725
2726    case ALT_CLK_PERIPHERAL_PLL_C5:
2727    case ALT_CLK_H2F_USER1:
2728        *div = (ALT_CLKMGR_PERPLL_S2FUSER1CLK_CNT_GET(alt_read_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR))) + 1;
2729        break;
2730
2731        /////
2732
2733        // SDRAM PLL outputs
2734    case ALT_CLK_SDRAM_PLL_C0:
2735    case ALT_CLK_DDR_DQS:
2736        *div = (ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR))) + 1;
2737        break;
2738
2739    case ALT_CLK_SDRAM_PLL_C1:
2740    case ALT_CLK_DDR_2X_DQS:
2741        *div = (ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR))) + 1;
2742        break;
2743
2744    case ALT_CLK_SDRAM_PLL_C2:
2745    case ALT_CLK_DDR_DQ:
2746        *div = (ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR))) + 1;
2747        break;
2748
2749    case ALT_CLK_SDRAM_PLL_C5:
2750    case ALT_CLK_H2F_USER2:
2751        *div = (ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_GET(alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR))) + 1;
2752        break;
2753
2754        /////
2755
2756        // Other clock dividers
2757    case ALT_CLK_L3_MP:
2758        temp = ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
2759        if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_E_DIV2)
2760        {
2761            *div = temp + 1;
2762        }
2763        else
2764        {
2765            status = ALT_E_ERROR;
2766        }
2767        break;
2768
2769    case ALT_CLK_L3_SP:
2770        temp = ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
2771        if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_E_DIV2)
2772        {
2773            *div = temp + 1;
2774        }
2775        else
2776        {
2777            status = ALT_E_ERROR;
2778        }
2779        // note that this value does not include the additional effect
2780        // of the L3_MP divider that is upchain from this one
2781        break;
2782
2783    case ALT_CLK_L4_MP:
2784        temp = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
2785        if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV16)
2786        {
2787            *div = 1 << temp;
2788        }
2789        else
2790        {
2791            status = ALT_E_ERROR;
2792        }
2793        break;
2794
2795    case ALT_CLK_L4_SP:
2796        temp = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR));
2797        if (temp <= ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV16)
2798        {
2799            *div = 1 << temp;
2800        }
2801        else
2802        {
2803            status = ALT_E_ERROR;
2804        }
2805        break;
2806
2807    case ALT_CLK_DBG_AT:
2808        temp = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR));
2809        if (temp <= ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV4)
2810        {
2811            *div = 1 << temp;
2812        }
2813        else
2814        {
2815            status = ALT_E_ERROR;
2816        }
2817        break;
2818
2819    case ALT_CLK_DBG:
2820        temp = ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR));
2821        if (temp <= ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_E_DIV4)
2822        {
2823            *div =  1 << temp;
2824        }
2825        else
2826        {
2827            status = ALT_E_ERROR;
2828        }
2829        // note that this value does not include the value of the upstream dbg_at_clk divder
2830        break;
2831
2832    case ALT_CLK_DBG_TRACE:
2833        temp = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_GET(alt_read_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR));
2834        if (temp <= ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV16)
2835        {
2836            *div =  1 << temp;
2837        }
2838        else
2839        {
2840            status = ALT_E_ERROR;
2841        }
2842        break;
2843
2844    case ALT_CLK_USB_MP:
2845        temp = ALT_CLKMGR_PERPLL_DIV_USBCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
2846        if (temp <= ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV16)
2847        {
2848            *div = 1 << temp;
2849        }
2850        else
2851        {
2852            status = ALT_E_ERROR;
2853        }
2854        break;
2855
2856    case ALT_CLK_SPI_M:
2857        temp = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
2858        if (temp <= ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV16)
2859        {
2860            *div = 1 << temp;
2861        }
2862        else
2863        {
2864            status = ALT_E_ERROR;
2865        }
2866        break;
2867
2868    case ALT_CLK_CAN0:
2869        temp = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
2870        if (temp <= ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV16)
2871        {
2872            *div = 1 << temp;
2873        }
2874        else
2875        {
2876            status = ALT_E_ERROR;
2877        }
2878        break;
2879
2880    case ALT_CLK_CAN1:
2881        temp = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR));
2882        if (temp <= ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV16)
2883        {
2884            *div = 1 << temp;
2885        }
2886        else
2887        {
2888            status = ALT_E_ERROR;
2889        }
2890        break;
2891
2892    case ALT_CLK_GPIO_DB:
2893        temp = ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_GET(alt_read_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR));
2894        *div = temp + 1;
2895        break;
2896
2897    case ALT_CLK_MPU_PERIPH:
2898        *div = 4;                           // set by hardware
2899        break;
2900
2901    case ALT_CLK_MPU_L2_RAM:
2902        *div = 2;                           // set by hardware
2903        break;
2904
2905    case ALT_CLK_NAND:
2906        *div = 4;                           // set by hardware
2907        break;
2908
2909    default:
2910        status = ALT_E_BAD_ARG;
2911        break;
2912    }
2913
2914    return status;
2915}
2916
2917/////
2918
2919#define ALT_CLK_WITHIN_FREQ_LIMITS_TEST_MODE        false
2920    // used for testing writes to the the full range of counters without
2921    // regard to the usual output frequency upper and lower limits
2922
2923
2924static ALT_STATUS_CODE alt_clk_within_freq_limits(ALT_CLK_t clk, uint32_t div)
2925{
2926#if ALT_CLK_WITHIN_FREQ_LIMITS_TEST_MODE
2927    return ALT_E_TRUE;
2928#else
2929
2930    if (div == 0)
2931    {
2932        return ALT_E_BAD_ARG;
2933    }
2934
2935    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2936    uint32_t        numer = 0;
2937    uint32_t        hilimit;
2938    uint32_t        lolimit;
2939
2940    switch (clk)
2941    {
2942        // Counters of the Main PLL
2943    case ALT_CLK_MAIN_PLL_C0:
2944        hilimit = alt_pll_cntr_maxfreq.MainPLL_C0;
2945        lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
2946        status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
2947        break;
2948    case  ALT_CLK_MAIN_PLL_C1:
2949        hilimit = alt_pll_cntr_maxfreq.MainPLL_C1;
2950        lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
2951        status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
2952        break;
2953    case ALT_CLK_MAIN_PLL_C2:
2954        hilimit = alt_pll_cntr_maxfreq.MainPLL_C2;
2955        lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
2956        status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
2957        break;
2958    case ALT_CLK_MAIN_PLL_C3:
2959        hilimit = alt_pll_cntr_maxfreq.MainPLL_C3;
2960        lolimit = 0;
2961        status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
2962        break;
2963    case ALT_CLK_MAIN_PLL_C4:
2964        hilimit = alt_pll_cntr_maxfreq.MainPLL_C4;
2965        lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
2966        status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
2967        break;
2968    case ALT_CLK_MAIN_PLL_C5:
2969        hilimit = alt_pll_cntr_maxfreq.MainPLL_C5;
2970        lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
2971        status = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &numer);
2972        break;
2973
2974    // Counters of the Peripheral PLL
2975    case ALT_CLK_PERIPHERAL_PLL_C0:
2976        hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C0;
2977        lolimit = 0;
2978        status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
2979        break;
2980    case ALT_CLK_PERIPHERAL_PLL_C1:
2981        hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C1;
2982        lolimit = 0;
2983        status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
2984        break;
2985    case ALT_CLK_PERIPHERAL_PLL_C2:
2986        hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C2;
2987        lolimit = 0;
2988        status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
2989        break;
2990    case ALT_CLK_PERIPHERAL_PLL_C3:
2991        hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C3;
2992        lolimit = 0;
2993        status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
2994        break;
2995    case ALT_CLK_PERIPHERAL_PLL_C4:
2996        hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C4;
2997        lolimit = 0;
2998        status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
2999        break;
3000    case ALT_CLK_PERIPHERAL_PLL_C5:
3001        hilimit = alt_pll_cntr_maxfreq.PeriphPLL_C5;
3002        lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
3003        status = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &numer);
3004        break;
3005
3006    // Counters of the SDRAM PLL
3007    case ALT_CLK_SDRAM_PLL_C0:
3008        hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C0;
3009        lolimit = 0;
3010        status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
3011        break;
3012    case ALT_CLK_SDRAM_PLL_C1:
3013        hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C1;
3014        lolimit = 0;
3015        status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
3016        break;
3017    case ALT_CLK_SDRAM_PLL_C2:
3018        hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C2;
3019        lolimit = 0;
3020        status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
3021        break;
3022    case ALT_CLK_SDRAM_PLL_C5:
3023        hilimit = alt_pll_cntr_maxfreq.SDRAMPLL_C5;
3024        lolimit = alt_ext_clk_paramblok.clkosc1.freqcur;
3025        status = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &numer);
3026        break;
3027
3028    default:
3029        status = ALT_E_BAD_ARG;
3030        break;
3031    }
3032
3033    if (status == ALT_E_SUCCESS)
3034    {
3035        numer = numer / div;
3036        if ((numer <= hilimit) && (numer >= lolimit))
3037        {
3038            status = ALT_E_TRUE;
3039        }
3040        else
3041        {
3042            status = ALT_E_FALSE;
3043        }
3044    }
3045
3046    return status;
3047#endif
3048}
3049
3050static bool alt_clkmgr_is_val_modulo_n(uint32_t div, uint32_t mod)
3051{
3052    if (mod == 1)
3053    {
3054        return true;
3055    }
3056    else if (mod == 2)
3057    {
3058        return (div & 0x1) == 0;
3059    }
3060    else if (mod == 4)
3061    {
3062        return (div & 0x3) == 0;
3063    }
3064    else
3065    {
3066        return (div % mod) == 0;
3067    }
3068}
3069
3070//
3071// alt_clk_divider_set() sets the divider value for the specified clock.
3072//
3073// See pages 38, 44, 45, and 46 of the HPS-Clocking NPP for a map of the
3074// HPS clocking architecture and hierarchy of connections.
3075//
3076ALT_STATUS_CODE alt_clk_divider_set(ALT_CLK_t clk, uint32_t div)
3077{
3078    ALT_STATUS_CODE     ret = ALT_E_BAD_ARG;
3079    volatile uint32_t   temp, temp1;
3080    uint32_t            wrval = UINT32_MAX;              // value to be written
3081    bool                restore_0 = false;
3082    bool                restore_1 = false;
3083    bool                restore_2 = false;
3084
3085    switch (clk)
3086    {
3087        // Main PLL outputs
3088    case ALT_CLK_MAIN_PLL_C0:
3089    case ALT_CLK_MPU:
3090        {
3091            uint32_t prediv = (ALT_CLKMGR_ALTERA_MPUCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MPUCLK_ADDR)) + 1);
3092
3093            if (   (div <= ((ALT_CLKMGR_MAINPLL_MPUCLK_CNT_SET_MSK + 1) * prediv))
3094                && alt_clkmgr_is_val_modulo_n(div, prediv)
3095                && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C0, div) == ALT_E_TRUE) )
3096            {
3097                wrval = (div / prediv) - 1;
3098
3099                // HW managed clock, change by writing to the external counter,  no need to gate clock
3100                // or match phase or wait for transistion time. No other field in the register to mask off either.
3101                alt_write_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR, wrval);
3102                ret = ALT_E_SUCCESS;
3103            }
3104            else
3105            {
3106                ret = ALT_E_ARG_RANGE;
3107            }
3108        }
3109        break;
3110
3111    case ALT_CLK_MAIN_PLL_C1:
3112    case ALT_CLK_L3_MAIN:
3113        {
3114            uint32_t prediv = (ALT_CLKMGR_ALTERA_MAINCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_MAINCLK_ADDR)) + 1);
3115
3116            if (   (div <= ((ALT_CLKMGR_MAINPLL_MAINCLK_CNT_SET_MSK + 1) * prediv))
3117                && alt_clkmgr_is_val_modulo_n(div, prediv)
3118                && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C1, div) == ALT_E_TRUE) )
3119            {
3120                // HW managed clock, change by writing to the external counter, no need to gate clock
3121                // or match phase or wait for transistion time. No other field in the register to mask off either.
3122
3123                wrval = (div / prediv) - 1;
3124
3125#if ALT_PREVENT_GLITCH_CHGC1
3126                // if L4MP or L4SP source is set to Main PLL C1, gate it off before changing
3127                // bypass state, then gate clock back on. FogBugz #63778
3128                temp  = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
3129                temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3130
3131                if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4MP_SET_MSK)))
3132                {
3133                    restore_0 = true;
3134                }
3135                if ((temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK) && (!(temp & ALT_CLKMGR_MAINPLL_L4SRC_L4SP_SET_MSK)))
3136                {
3137                    restore_1 = true;
3138                }
3139                temp = temp1;
3140                if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
3141                if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
3142                if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp); }
3143
3144                alt_write_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR, wrval);
3145
3146                alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3147                // wait a bit before reenabling the L4MP and L4SP clocks
3148                if (restore_0 || restore_1) { alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp1); }
3149#else
3150                alt_write_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR, wrval);
3151#endif
3152                ret = ALT_E_SUCCESS;
3153            }
3154            else
3155            {
3156                ret = ALT_E_ARG_RANGE;
3157            }
3158        }
3159        break;
3160
3161    case ALT_CLK_MAIN_PLL_C2:
3162    case ALT_CLK_DBG_BASE:
3163        {
3164            uint32_t prediv = (ALT_CLKMGR_ALTERA_DBGATCLK_CNT_GET(alt_read_word(ALT_CLKMGR_ALTERA_DBGATCLK_ADDR)) + 1);
3165
3166            if (   (div <= ((ALT_CLKMGR_MAINPLL_DBGATCLK_CNT_SET_MSK + 1) * prediv))
3167                   && alt_clkmgr_is_val_modulo_n(div, prediv)
3168                && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C2, div) == ALT_E_TRUE) )
3169            {
3170                wrval = (div / prediv) - 1;
3171                // HW managed clock, change by writing to the external counter,  no need to gate clock
3172                // or match phase or wait for transistion time. No other field in the register to mask off either.
3173                alt_write_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR, wrval);
3174
3175                ret = ALT_E_SUCCESS;
3176            }
3177            else
3178            {
3179                ret = ALT_E_ARG_RANGE;
3180            }
3181        }
3182        break;
3183
3184    case ALT_CLK_MAIN_PLL_C3:
3185        // The rest of the PLL outputs do not have external counters, but
3186        // their internal counters are programmable rather than fixed
3187        if (   (div <= (ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_SET_MSK + 1))
3188            && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C3, div) == ALT_E_TRUE) )
3189        {
3190            // if the main_qspi_clk input is selected for the qspi_clk
3191            if (ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR)) ==
3192                ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
3193            {
3194                restore_0 = (temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR)) & ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK;
3195                if (restore_0)             // AND if the QSPI clock is currently enabled
3196                {
3197                    alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_QSPICLK_CLR_MSK);
3198                    // gate off the QSPI clock
3199                }
3200
3201                wrval = div - 1;
3202                // the rest are software-managed clocks and require a reset sequence to write to
3203                alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
3204                                         ALT_CLKMGR_MAINPLL_STAT_ADDR,
3205                                         ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR,
3206                                         wrval,
3207                                         ALT_CLK_PLL_RST_BIT_C3,
3208                                         ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
3209
3210                alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3211                if (restore_0)
3212                {
3213                    alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3214                    // if the QSPI clock was gated on (enabled) before, return it to that state
3215                }
3216                ret = ALT_E_SUCCESS;
3217            }
3218        }
3219        else
3220        {
3221            ret = ALT_E_ARG_RANGE;
3222        }
3223        break;
3224
3225    case ALT_CLK_MAIN_PLL_C4:
3226    case ALT_CLK_MAIN_NAND_SDMMC:
3227        if (   (div <= (ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_CNT_SET_MSK + 1))
3228            && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C4, div) == ALT_E_TRUE) )
3229        {
3230            temp  = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
3231            temp1 = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3232
3233            // do we need to gate off the SDMMC clock ?
3234            if (ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(temp) == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK)
3235            {
3236                if (temp1 & ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK) { restore_0 = true; }
3237            }
3238
3239            // do we need to gate off the NAND clock and/or the NANDX clock?
3240            if (ALT_CLKMGR_PERPLL_SRC_NAND_GET(temp) == ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK)
3241            {
3242                if (temp1 & ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK) { restore_1 = true; }
3243                if (temp1 & ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK)  { restore_2 = true; }
3244            }
3245
3246            temp = temp1;
3247            if (restore_1 && restore_2)
3248            {
3249                temp &= ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK;
3250                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3251                alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
3252                // gate nand_clk off at least 8 MPU clock cycles before before nand_x_clk
3253            }
3254
3255            if (restore_0 || restore_1)
3256            {
3257                if (restore_0) { temp &= ALT_CLKMGR_PERPLL_EN_SDMMCCLK_CLR_MSK; }
3258                if (restore_1) { temp &= ALT_CLKMGR_PERPLL_EN_NANDXCLK_CLR_MSK; }
3259                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3260                // gate off sdmmc_clk and/or nand_x_clk
3261            }
3262
3263            // now write the new divisor ratio
3264            wrval = div - 1;
3265            alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
3266                                     ALT_CLKMGR_MAINPLL_STAT_ADDR,
3267                                     ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR,
3268                                     wrval,
3269                                     ALT_CLK_PLL_RST_BIT_C4,
3270                                     ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
3271            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3272
3273            if (restore_0 || restore_1)
3274            {
3275                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1 & ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK);
3276                // if the NANDX and/or SDMMC clock was gated on (enabled) before, return it to that state
3277                if (restore_1 && restore_2)
3278                {
3279                    // wait at least 8 clock cycles to turn the nand_clk on
3280                    alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
3281                    alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1);
3282                }
3283            }
3284            ret = ALT_E_SUCCESS;
3285        }
3286        else
3287        {
3288            ret = ALT_E_ARG_RANGE;
3289        }
3290        break;
3291
3292    case ALT_CLK_MAIN_PLL_C5:
3293    case ALT_CLK_CFG:
3294    case ALT_CLK_H2F_USER0:
3295        if (   (div <= (ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_CNT_SET_MSK + 1))
3296            && (alt_clk_within_freq_limits(ALT_CLK_MAIN_PLL_C5, div) == ALT_E_TRUE) )
3297        {
3298            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3299            restore_0 = ((temp & ALT_CLKMGR_MAINPLL_EN_CFGCLK_SET_MSK) ||
3300                         (temp & ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_SET_MSK));
3301            if (restore_0)
3302            {
3303                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & (ALT_CLKMGR_MAINPLL_EN_CFGCLK_CLR_MSK &
3304                                                                   ALT_CLKMGR_MAINPLL_EN_S2FUSER0CLK_CLR_MSK)); // clear both
3305            }
3306
3307            // now write the new divisor ratio
3308            wrval = div - 1;
3309            alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
3310                                     ALT_CLKMGR_MAINPLL_STAT_ADDR,
3311                                     ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR,
3312                                     wrval,
3313                                     ALT_CLK_PLL_RST_BIT_C5,
3314                                     ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
3315
3316            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3317
3318            if (restore_0)
3319            {
3320                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
3321            }
3322            ret = ALT_E_SUCCESS;
3323        }
3324        else
3325        {
3326            ret = ALT_E_ARG_RANGE;
3327        }
3328        break;
3329
3330        /////
3331
3332        // Peripheral PLL outputs
3333    case ALT_CLK_PERIPHERAL_PLL_C0:
3334    case ALT_CLK_EMAC0:
3335        if (   (div <= (ALT_CLKMGR_PERPLL_EMAC0CLK_CNT_SET_MSK + 1))
3336            && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C0, div) == ALT_E_TRUE) )
3337        {
3338            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3339            restore_0 = temp & ALT_CLKMGR_PERPLL_EN_EMAC0CLK_SET_MSK;
3340
3341            if (restore_0)
3342            {
3343                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_EMAC0CLK_CLR_MSK);
3344            }
3345
3346            // now write the new divisor ratio
3347            wrval = div - 1;
3348            alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
3349                                     ALT_CLKMGR_PERPLL_STAT_ADDR,
3350                                     ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR,
3351                                     wrval,
3352                                     ALT_CLK_PLL_RST_BIT_C0,
3353                                     ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
3354
3355            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3356            if (restore_0)
3357            {
3358                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3359            }
3360            ret = ALT_E_SUCCESS;
3361        }
3362        else
3363        {
3364            ret = ALT_E_ARG_RANGE;
3365        }
3366        break;
3367
3368    case ALT_CLK_PERIPHERAL_PLL_C1:
3369    case ALT_CLK_EMAC1:
3370        if (   (div <= (ALT_CLKMGR_PERPLL_EMAC1CLK_CNT_SET_MSK + 1))
3371            && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C1, div) == ALT_E_TRUE) )
3372        {
3373            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3374            restore_0 = temp & ALT_CLKMGR_PERPLL_EN_EMAC1CLK_SET_MSK;
3375
3376            if (restore_0)
3377            {
3378                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_EMAC1CLK_CLR_MSK);
3379            }
3380            // now write the new divisor ratio
3381            wrval = div - 1;
3382            alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
3383                                     ALT_CLKMGR_PERPLL_STAT_ADDR,
3384                                     ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR,
3385                                     wrval,
3386                                     ALT_CLK_PLL_RST_BIT_C1,
3387                                     ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
3388
3389            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3390            if (restore_0)
3391            {
3392                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3393            }
3394            ret = ALT_E_SUCCESS;
3395        }
3396        else
3397        {
3398            ret = ALT_E_ARG_RANGE;
3399        }
3400        break;
3401
3402    case ALT_CLK_PERIPHERAL_PLL_C2:
3403        if (   (div <= (ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_SET_MSK + 1))
3404            && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C2, div) == ALT_E_TRUE) )
3405        {
3406            temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
3407            if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
3408            {
3409                // if qspi source is set to Peripheral PLL C2
3410                temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3411                // and if qspi_clk is enabled
3412                restore_0 = temp & ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK;
3413                if (restore_0)
3414                {
3415                    alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_QSPICLK_CLR_MSK);
3416                    // gate it off
3417                }
3418            }
3419
3420            // now write the new divisor ratio
3421            wrval = div - 1;
3422            alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
3423                                     ALT_CLKMGR_PERPLL_STAT_ADDR,
3424                                     ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR,
3425                                     wrval,
3426                                     ALT_CLK_PLL_RST_BIT_C2,
3427                                     ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
3428
3429            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3430            if (restore_0)
3431            {
3432                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3433                // if the clock was gated on (enabled) before, return it to that state
3434            }
3435            ret = ALT_E_SUCCESS;
3436        }
3437        else
3438        {
3439            ret = ALT_E_ARG_RANGE;
3440        }
3441        break;
3442
3443    case ALT_CLK_PERIPHERAL_PLL_C3:
3444        if (   (div <= (ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_CNT_SET_MSK + 1))
3445            && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C3, div) == ALT_E_TRUE) )
3446        {
3447            // first, are the clock MUX input selections currently set to use the clock we want to change?
3448            temp = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
3449            restore_0 = (ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(temp) == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK);
3450            restore_1 = restore_2 = (ALT_CLKMGR_PERPLL_SRC_NAND_GET(temp) == ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK);
3451
3452            // now AND those with the current state of the three gate enables
3453            // to get the clocks which must be gated off and then back on
3454            temp1 = temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3455            restore_0 = restore_0 && (temp & ALT_CLKMGR_PERPLL_EN_SDMMCCLK_SET_MSK);
3456            restore_1 = restore_1 && (temp & ALT_CLKMGR_PERPLL_EN_NANDXCLK_SET_MSK);
3457            restore_2 = restore_2 && (temp & ALT_CLKMGR_PERPLL_EN_NANDCLK_SET_MSK);
3458
3459            // gate off the clocks that depend on the clock divider that we want to change
3460            if (restore_2) { temp &= ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK; }
3461            if (restore_0) { temp &= ALT_CLKMGR_PERPLL_EN_SDMMCCLK_CLR_MSK; }
3462            alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3463
3464            // the NAND clock must be gated off before the NANDX clock,
3465            if (restore_1)
3466            {
3467                alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK);
3468                temp &= ALT_CLKMGR_PERPLL_EN_NANDXCLK_CLR_MSK;
3469                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3470            }
3471
3472            // now write the new divisor ratio
3473            wrval = div - 1;
3474            alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
3475                                     ALT_CLKMGR_PERPLL_STAT_ADDR,
3476                                     ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR,
3477                                     wrval,
3478                                     ALT_CLK_PLL_RST_BIT_C3,
3479                                     ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
3480
3481            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
3482
3483            // NAND clock and NAND_X clock cannot be written together, must be a set sequence with a delay
3484            alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1 & ALT_CLKMGR_PERPLL_EN_NANDCLK_CLR_MSK);
3485            if (restore_2)
3486            {
3487                // the NANDX clock must be gated on before the NAND clock.
3488                alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_NANDCLK );
3489                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1);
3490            }
3491            ret = ALT_E_SUCCESS;
3492        }
3493        else
3494        {
3495            ret = ALT_E_ARG_RANGE;
3496        }
3497        break;
3498
3499    case ALT_CLK_PERIPHERAL_PLL_C4:
3500        if (   (div <= (ALT_CLKMGR_PERPLL_PERBASECLK_CNT_SET_MSK + 1))
3501            && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C4, div) == ALT_E_TRUE) )
3502        {
3503            // look at the L4 set of clock gates first
3504            temp1 = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
3505            restore_0 = (ALT_CLKMGR_MAINPLL_L4SRC_L4MP_GET(temp1) == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_PERIPHPLL);
3506            restore_1 = (ALT_CLKMGR_MAINPLL_L4SRC_L4SP_GET(temp1) == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_PERIPHPLL);
3507            temp1 = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3508            restore_0 = restore_0 && (temp1 & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK);
3509            restore_1 = restore_1 && (temp1 & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK);
3510
3511            // if the l4_sp and l4_mp clocks are not set to use the periph_base_clk
3512            // from the Peripheral PLL C4 clock divider output, or if they are
3513            // not currently gated on, don't change their gates
3514            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3515            if (restore_0) { temp &= ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK; }
3516            if (restore_1) { temp &= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK; }
3517            alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
3518
3519            // now look at the C4 direct set of clock gates
3520            // first, create a mask of the C4 direct set of clock gate enables
3521            temp = (  ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK
3522                    | ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK
3523                    | ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK
3524                    | ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK
3525                    | ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK );
3526
3527            // gate off all the C4 Direct set of clocks
3528            alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1 & ~temp);
3529
3530            // change the clock divider ratio - the reason we're here
3531            wrval = div - 1;
3532            alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
3533                                     ALT_CLKMGR_PERPLL_STAT_ADDR,
3534                                     ALT_CLKMGR_PERPLL_PERBASECLK_ADDR,
3535                                     wrval,
3536                                     ALT_CLK_PLL_RST_BIT_C4,
3537                                     ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
3538
3539            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
3540
3541            // gate the affected clocks that were on before back on - both sets of gates
3542            temp = (restore_0) ? ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK : 0;
3543            if (restore_1) { temp |= ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK; }
3544            alt_setbits_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
3545            alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp1);
3546            ret = ALT_E_SUCCESS;
3547        }
3548        else
3549        {
3550            ret = ALT_E_ARG_RANGE;
3551        }
3552        break;
3553
3554    case ALT_CLK_PERIPHERAL_PLL_C5:
3555    case ALT_CLK_H2F_USER1:
3556        if (   (div <= (ALT_CLKMGR_PERPLL_S2FUSER1CLK_CNT_SET_MSK + 1))
3557            && (alt_clk_within_freq_limits(ALT_CLK_PERIPHERAL_PLL_C5, div) == ALT_E_TRUE) )
3558        {
3559            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3560            restore_0 = temp & ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_SET_MSK;
3561            if (restore_0)
3562            {
3563                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_S2FUSER1CLK_CLR_MSK);
3564            }
3565
3566            // now write the new divisor ratio
3567            wrval = div - 1;
3568            alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
3569                                     ALT_CLKMGR_PERPLL_STAT_ADDR,
3570                                     ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR,
3571                                     wrval,
3572                                     ALT_CLK_PLL_RST_BIT_C5,
3573                                     ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
3574
3575            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
3576            if (restore_0) { alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp); }
3577            ret = ALT_E_SUCCESS;
3578        }
3579        else
3580        {
3581            ret = ALT_E_ARG_RANGE;
3582        }
3583        break;
3584
3585        /////
3586
3587        // SDRAM PLL outputs
3588    case ALT_CLK_SDRAM_PLL_C0:
3589    case ALT_CLK_DDR_DQS:
3590        if (   (div <= (ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_SET_MSK + 1))
3591            && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C0, div) == ALT_E_TRUE) )
3592        {
3593            wrval = div - 1;
3594            temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
3595            if (temp & ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_SET_MSK)
3596            {
3597                // if clock is currently on, gate it off
3598                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_DDRDQSCLK_CLR_MSK);
3599                restore_0 = true;
3600            }
3601
3602            alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
3603                                     ALT_CLKMGR_SDRPLL_STAT_ADDR,
3604                                     ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR,
3605                                     wrval,
3606                                     ALT_CLK_PLL_RST_BIT_C0,
3607                                     ALT_CLKMGR_SDRPLL_DDRDQSCLK_CNT_LSB);
3608            if (restore_0)
3609            {
3610                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp);         // which has the enable bit set
3611            }
3612            ret = ALT_E_SUCCESS;
3613        }
3614        else
3615        {
3616            ret = ALT_E_ARG_RANGE;
3617        }
3618        break;
3619
3620    case ALT_CLK_SDRAM_PLL_C1:
3621    case ALT_CLK_DDR_2X_DQS:
3622        if (   (div <= (ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_CNT_SET_MSK + 1))
3623            && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C1, div) == ALT_E_TRUE) )
3624        {
3625            wrval = div - 1;
3626            temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
3627            if (temp & ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_SET_MSK)
3628            {
3629                // if clock is currently on, gate it off
3630                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_DDR2XDQSCLK_CLR_MSK);
3631                restore_0 = true;
3632            }
3633
3634            alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
3635                                     ALT_CLKMGR_SDRPLL_STAT_ADDR,
3636                                     ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR,
3637                                     wrval,
3638                                     ALT_CLK_PLL_RST_BIT_C1,
3639                                     ALT_CLKMGR_SDRPLL_VCO_OUTRST_LSB);
3640            if (restore_0)
3641            {
3642                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp);         // which has the enable bit set
3643            }
3644            ret = ALT_E_SUCCESS;
3645        }
3646        else
3647        {
3648            ret = ALT_E_ARG_RANGE;
3649        }
3650        break;
3651
3652    case ALT_CLK_SDRAM_PLL_C2:
3653    case ALT_CLK_DDR_DQ:
3654        if (   (div <= (ALT_CLKMGR_SDRPLL_DDRDQCLK_CNT_SET_MSK + 1))
3655            && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C2, div) == ALT_E_TRUE) )
3656        {
3657            wrval = div - 1;
3658            temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
3659            if (temp & ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_SET_MSK)
3660            {
3661                // if clock is currently on, gate it off
3662                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_DDRDQCLK_CLR_MSK);
3663                restore_0 = true;
3664            }
3665
3666            alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
3667                                     ALT_CLKMGR_SDRPLL_STAT_ADDR,
3668                                     ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR,
3669                                     wrval,
3670                                     ALT_CLK_PLL_RST_BIT_C2,
3671                                     ALT_CLKMGR_SDRPLL_VCO_OUTRST_LSB);
3672            if (restore_0)
3673            {
3674                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp);         // which has the enable bit set
3675            }
3676            ret = ALT_E_SUCCESS;
3677        }
3678        else
3679        {
3680            ret = ALT_E_ARG_RANGE;
3681        }
3682        break;
3683
3684    case ALT_CLK_SDRAM_PLL_C5:
3685    case ALT_CLK_H2F_USER2:
3686        if (   (div <= (ALT_CLKMGR_SDRPLL_S2FUSER2CLK_CNT_SET_MSK + 1))
3687            && (alt_clk_within_freq_limits(ALT_CLK_SDRAM_PLL_C5, div) == ALT_E_TRUE) )
3688        {
3689            wrval = div - 1;
3690            temp = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
3691            if (temp & ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_SET_MSK)
3692            {
3693                // if clock is currently on, gate it off
3694                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp & ALT_CLKMGR_SDRPLL_EN_S2FUSER2CLK_CLR_MSK);
3695                restore_0 = true;
3696            }
3697
3698            alt_clk_pllcounter_write(ALT_CLKMGR_SDRPLL_VCO_ADDR,
3699                                     ALT_CLKMGR_SDRPLL_STAT_ADDR,
3700                                     ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR,
3701                                     wrval,
3702                                     ALT_CLK_PLL_RST_BIT_C5,
3703                                     ALT_CLKMGR_SDRPLL_VCO_OUTRST_LSB);
3704            if (restore_0)
3705            {
3706                alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, temp);         // which has the enable bit set
3707            }
3708            ret = ALT_E_SUCCESS;
3709        }
3710        else
3711        {
3712            ret = ALT_E_ARG_RANGE;
3713        }
3714        break;
3715
3716        /////
3717
3718        // Other clock dividers
3719    case ALT_CLK_L3_MP:
3720        if      (div == 1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_E_DIV1; }
3721        else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_E_DIV2; }
3722
3723        if (wrval != UINT32_MAX)
3724        {
3725            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3726            if (temp & ALT_CLKMGR_MAINPLL_EN_L3MPCLK_SET_MSK)
3727            {
3728                // if clock is currently on, gate it off
3729                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_L3MPCLK_CLR_MSK);
3730                restore_0 = true;
3731            }
3732            alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_SET_MSK,
3733                              wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L3MPCLK_LSB);
3734            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_EN_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
3735            if (restore_0)
3736            {
3737                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);         // which has the enable bit set
3738            }
3739            ret = ALT_E_SUCCESS;
3740        }
3741        else
3742        {
3743            ret = ALT_E_ARG_RANGE;
3744        }
3745        break;
3746
3747    case ALT_CLK_L3_SP:
3748        // note that the L3MP divider is upstream from the L3SP divider
3749        // and any changes to the former will affect the output of both
3750        if      (div == 1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_E_DIV1; }
3751        else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_E_DIV2; }
3752
3753        if (wrval != UINT32_MAX)
3754        {
3755            alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_SET_MSK,
3756                              wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L3SPCLK_LSB);
3757            // no clock gate to close and reopen
3758            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV );
3759            ret = ALT_E_SUCCESS;
3760        }
3761        else
3762        {
3763            ret = ALT_E_ARG_RANGE;
3764        }
3765        break;
3766
3767    case ALT_CLK_L4_MP:
3768        if      (div ==  1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV1; }
3769        else if (div ==  2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV2; }
3770        else if (div ==  4) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV4; }
3771        else if (div ==  8) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV8; }
3772        else if (div == 16) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_E_DIV16; }
3773
3774        if (wrval != UINT32_MAX)
3775        {
3776            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3777            if (temp & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_SET_MSK)
3778            {
3779                // if clock is currently on, gate it off
3780                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_L4MPCLK_CLR_MSK);
3781                restore_0 = true;
3782            }
3783            alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_SET_MSK,
3784                              wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L4MPCLK_LSB);
3785            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3786            if (restore_0)
3787            {
3788                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);         // which has the enable bit set
3789            }
3790            ret = ALT_E_SUCCESS;
3791        }
3792        else
3793        {
3794            ret = ALT_E_ARG_RANGE;
3795        }
3796        break;
3797
3798    case ALT_CLK_L4_SP:
3799        if      (div ==  1) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV1; }
3800        else if (div ==  2) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV2; }
3801        else if (div ==  4) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV4; }
3802        else if (div ==  8) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV8; }
3803        else if (div == 16) { wrval = ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_E_DIV16; }
3804
3805        if (wrval != UINT32_MAX)
3806        {
3807            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3808            if (temp & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_SET_MSK)
3809            {
3810                // if clock is currently on, gate it off
3811                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_L4SPCLK_CLR_MSK);
3812                restore_0 = true;
3813            }
3814            alt_replbits_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_SET_MSK,
3815                              wrval << ALT_CLKMGR_MAINPLL_MAINDIV_L4SPCLK_LSB);
3816            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3817            if (restore_0)
3818            {
3819                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
3820            }
3821            ret = ALT_E_SUCCESS;
3822        }
3823        else
3824        {
3825            ret = ALT_E_ARG_RANGE;
3826        }
3827        break;
3828
3829    case ALT_CLK_DBG_AT:
3830        if      (div == 1) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV1; }
3831        else if (div == 2) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV2; }
3832        else if (div == 4) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_E_DIV4; }
3833
3834        if (wrval != UINT32_MAX)
3835        {
3836            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3837            if (temp & ALT_CLKMGR_MAINPLL_EN_DBGATCLK_SET_MSK)
3838            {
3839                // if clock is currently on, gate it off
3840                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_DBGATCLK_CLR_MSK);
3841                restore_0 = true;
3842            }
3843            alt_replbits_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_SET_MSK,
3844                              wrval << ALT_CLKMGR_MAINPLL_DBGDIV_DBGATCLK_LSB);
3845            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3846            if (restore_0)
3847            {
3848                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
3849            }
3850            ret = ALT_E_SUCCESS;
3851        }
3852        else
3853        {
3854            ret = ALT_E_ARG_RANGE;
3855        }
3856        break;
3857
3858    case ALT_CLK_DBG:
3859        if      (div == 2) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_E_DIV2; }
3860        else if (div == 4) { wrval = ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_E_DIV4; }
3861
3862        if (wrval != UINT32_MAX)
3863        {
3864            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3865            if (temp & ALT_CLKMGR_MAINPLL_EN_DBGCLK_SET_MSK)
3866            {
3867                // if clock is currently on, gate it off
3868                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_DBGCLK_CLR_MSK);
3869                restore_0 = true;
3870            }
3871            alt_replbits_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_SET_MSK,
3872                              wrval << (ALT_CLKMGR_MAINPLL_DBGDIV_DBGCLK_LSB - 1));
3873            // account for the fact that the divisor ratios are 2x the value
3874            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3875            if (restore_0)
3876            {
3877                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
3878            }
3879            ret = ALT_E_SUCCESS;
3880        }
3881        else
3882        {
3883            ret = ALT_E_ARG_RANGE;
3884        }
3885        break;
3886
3887    case ALT_CLK_DBG_TRACE:
3888        if      (div ==  1) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV1; }
3889        else if (div ==  2) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV2; }
3890        else if (div ==  4) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV4; }
3891        else if (div ==  8) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV8; }
3892        else if (div == 16) { wrval = ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_E_DIV16; }
3893
3894        if (wrval != UINT32_MAX)
3895        {
3896            temp = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
3897            if (temp & ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_SET_MSK)
3898            {
3899                // if clock is currently on, gate it off
3900                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp & ALT_CLKMGR_MAINPLL_EN_DBGTRACECLK_CLR_MSK);
3901                restore_0 = true;
3902            }
3903            alt_replbits_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR, ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_SET_MSK,
3904                              wrval << ALT_CLKMGR_MAINPLL_TRACEDIV_TRACECLK_LSB);
3905            alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3906            if (restore_0)
3907            {
3908                alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, temp);
3909            }
3910            ret = ALT_E_SUCCESS;
3911        }
3912        else
3913        {
3914            ret = ALT_E_ARG_RANGE;
3915        }
3916        break;
3917
3918    case ALT_CLK_USB_MP:
3919        if      (div ==  1) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV1; }
3920        else if (div ==  2) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV2; }
3921        else if (div ==  4) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV4; }
3922        else if (div ==  8) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV8; }
3923        else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_USBCLK_E_DIV16; }
3924
3925        if (wrval != UINT32_MAX)
3926        {
3927            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3928            if (temp & ALT_CLKMGR_PERPLL_EN_USBCLK_SET_MSK)
3929            {
3930                // if clock is currently on, gate it off
3931                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_USBCLK_CLR_MSK);
3932                restore_0 = true;
3933            }
3934            alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_USBCLK_SET_MSK,
3935                              wrval << ALT_CLKMGR_PERPLL_DIV_USBCLK_LSB);
3936            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3937            if (restore_0)
3938            {
3939                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3940            }
3941            ret = ALT_E_SUCCESS;
3942        }
3943        else
3944        {
3945            ret = ALT_E_ARG_RANGE;
3946        }
3947        break;
3948
3949    case ALT_CLK_SPI_M:
3950        if      (div ==  1) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV1; }
3951        else if (div ==  2) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV2; }
3952        else if (div ==  4) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV4; }
3953        else if (div ==  8) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV8; }
3954        else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_SPIMCLK_E_DIV16; }
3955
3956        if (wrval != UINT32_MAX)
3957        {
3958            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3959            if (temp & ALT_CLKMGR_PERPLL_EN_SPIMCLK_SET_MSK)
3960            {
3961                // if clock is currently on, gate it off
3962                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_SPIMCLK_CLR_MSK);
3963                restore_0 = true;
3964            }
3965            alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_SPIMCLK_SET_MSK,
3966                              wrval << ALT_CLKMGR_PERPLL_DIV_SPIMCLK_LSB);
3967            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3968            if (restore_0)
3969            {
3970                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
3971            }
3972            ret = ALT_E_SUCCESS;
3973        }
3974        else
3975        {
3976            ret = ALT_E_ARG_RANGE;
3977        }
3978        break;
3979
3980    case ALT_CLK_CAN0:
3981        if      (div ==  1) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV1; }
3982        else if (div ==  2) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV2; }
3983        else if (div ==  4) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV4; }
3984        else if (div ==  8) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV8; }
3985        else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN0CLK_E_DIV16; }
3986
3987        if (wrval != UINT32_MAX)
3988        {
3989            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
3990            if (temp & ALT_CLKMGR_PERPLL_EN_CAN0CLK_SET_MSK)
3991            {
3992                // if clock is currently on, gate it off
3993                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_CAN0CLK_CLR_MSK);
3994                restore_0 = true;
3995            }
3996            alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_CAN0CLK_SET_MSK,
3997                              wrval << ALT_CLKMGR_PERPLL_DIV_CAN0CLK_LSB);
3998            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
3999            if (restore_0)
4000            {
4001                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
4002            }
4003            ret = ALT_E_SUCCESS;
4004        }
4005        else
4006        {
4007            ret = ALT_E_ARG_RANGE;
4008        }
4009        break;
4010
4011    case ALT_CLK_CAN1:
4012        if      (div ==  1) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV1; }
4013        else if (div ==  2) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV2; }
4014        else if (div ==  4) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV4; }
4015        else if (div ==  8) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV8; }
4016        else if (div == 16) { wrval = ALT_CLKMGR_PERPLL_DIV_CAN1CLK_E_DIV16; }
4017
4018        if (wrval != UINT32_MAX)
4019        {
4020            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
4021            if (temp & ALT_CLKMGR_PERPLL_EN_CAN1CLK_SET_MSK)
4022            {
4023                // if clock is currently on, gate it off
4024                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_CAN1CLK_CLR_MSK);
4025                restore_0 = true;
4026            }
4027            alt_replbits_word(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_CLKMGR_PERPLL_DIV_CAN1CLK_SET_MSK,
4028                              wrval << ALT_CLKMGR_PERPLL_DIV_CAN1CLK_LSB);
4029            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_DIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
4030            if (restore_0)
4031            {
4032                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
4033            }
4034            ret = ALT_E_SUCCESS;
4035        }
4036        else
4037        {
4038            ret = ALT_E_ARG_RANGE;
4039        }
4040        break;
4041
4042    case ALT_CLK_GPIO_DB:           // GPIO debounce clock
4043        if (div <= ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET_MSK)
4044        {
4045            temp = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
4046            if (temp & ALT_CLKMGR_PERPLL_EN_GPIOCLK_SET_MSK)
4047            {
4048                // if clock is currently on, gate it off
4049                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp & ALT_CLKMGR_PERPLL_EN_GPIOCLK_CLR_MSK);
4050                restore_0 = true;
4051            }
4052            wrval = div - 1;
4053            alt_replbits_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR, ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET_MSK,
4054                              wrval << ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_LSB);
4055            alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_GPIODIV_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
4056            if (restore_0)
4057            {
4058                alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, temp);
4059            }
4060            ret = ALT_E_SUCCESS;
4061        }
4062        else
4063        {
4064            ret = ALT_E_ARG_RANGE;
4065        }
4066        break;
4067
4068    case ALT_CLK_MAIN_QSPI:
4069        temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
4070        // get the QSPI clock source
4071        restore_0 = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR) & ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK;
4072        // and the current enable state
4073        wrval = div - 1;
4074
4075        if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
4076        {           // if the main_qspi_clk (Main PLL C3 Ouput) input is selected
4077            if (div <= ALT_CLKMGR_MAINPLL_MAINQSPICLK_CNT_SET_MSK)
4078            {
4079                if (restore_0)
4080                {
4081                    alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
4082                }                // gate off the QSPI clock
4083
4084                alt_clk_pllcounter_write(ALT_CLKMGR_MAINPLL_VCO_ADDR,
4085                                         ALT_CLKMGR_MAINPLL_STAT_ADDR,
4086                                         ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR,
4087                                         wrval,
4088                                         ALT_CLK_PLL_RST_BIT_C3,
4089                                         ALT_CLKMGR_MAINPLL_VCO_OUTRST_LSB);
4090
4091                alt_clk_mgr_wait(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
4092                if (restore_0)
4093                {
4094                    alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
4095                    // if the QSPI clock was gated on (enabled) before, return it to that state
4096                }
4097                ret = ALT_E_SUCCESS;
4098            }
4099            else
4100            {
4101                ret = ALT_E_ARG_RANGE;
4102            }
4103        }
4104        else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
4105        {
4106            if (div <= ALT_CLKMGR_PERPLL_PERQSPICLK_CNT_SET_MSK)
4107            {
4108                if (restore_0)
4109                {
4110                    alt_clrbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
4111                }                // gate off the QSPI clock
4112
4113                alt_clk_pllcounter_write(ALT_CLKMGR_PERPLL_VCO_ADDR,
4114                                         ALT_CLKMGR_PERPLL_STAT_ADDR,
4115                                         ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR,
4116                                         wrval,
4117                                         ALT_CLK_PLL_RST_BIT_C2,
4118                                         ALT_CLKMGR_PERPLL_VCO_OUTRST_LSB);
4119
4120                alt_clk_mgr_wait(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR, ALT_SW_MANAGED_CLK_WAIT_CTRDIV);
4121                if (restore_0)
4122                {
4123                    alt_setbits_word(ALT_CLKMGR_PERPLL_EN_ADDR, ALT_CLKMGR_PERPLL_EN_QSPICLK_SET_MSK);
4124                    // if the QSPI clock was gated on (enabled) before, return it to that state
4125                }
4126                ret = ALT_E_SUCCESS;
4127            }
4128            else
4129            {
4130                ret = ALT_E_ARG_RANGE;
4131            }
4132        }
4133        break;
4134
4135        /////
4136
4137    default:
4138        ret = ALT_E_BAD_ARG;
4139        break;
4140    }
4141
4142    return ret;
4143}
4144
4145//
4146// alt_clk_freq_get() returns the output frequency of the specified clock.
4147//
4148ALT_STATUS_CODE alt_clk_freq_get(ALT_CLK_t clk, alt_freq_t* freq)
4149{
4150    ALT_STATUS_CODE ret = ALT_E_BAD_ARG;
4151    uint32_t        temp = 0;
4152    uint64_t        numer = 0;
4153    uint64_t        denom = 1;
4154
4155    if (freq == NULL)
4156        {
4157                return ret;
4158        }
4159
4160    switch (clk)
4161    {
4162        // External Inputs
4163    case ALT_CLK_IN_PIN_OSC1:
4164    case ALT_CLK_OSC1:
4165        numer = alt_ext_clk_paramblok.clkosc1.freqcur;
4166        // denom = 1 by default
4167        ret = ALT_E_SUCCESS;
4168        break;
4169
4170    case ALT_CLK_IN_PIN_OSC2:
4171        numer = alt_ext_clk_paramblok.clkosc2.freqcur;
4172        // denom = 1 by default
4173        ret = ALT_E_SUCCESS;
4174        break;
4175
4176    case ALT_CLK_F2H_PERIPH_REF:
4177        numer = alt_ext_clk_paramblok.periph.freqcur;
4178        // denom = 1 by default
4179        ret = ALT_E_SUCCESS;
4180        break;
4181
4182    case ALT_CLK_F2H_SDRAM_REF:
4183        numer = alt_ext_clk_paramblok.sdram.freqcur;
4184        // denom = 1 by default
4185        ret = ALT_E_SUCCESS;
4186        break;
4187
4188        /////
4189
4190        // PLLs
4191    case ALT_CLK_MAIN_PLL:
4192        if (alt_clk_pll_is_bypassed(ALT_CLK_MAIN_PLL) == ALT_E_TRUE)
4193        {
4194            temp = alt_ext_clk_paramblok.clkosc1.freqcur;
4195            ret = ALT_E_SUCCESS;
4196        }
4197        else
4198        {
4199            ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4200        }
4201        numer = (uint64_t) temp;
4202        // denom = 1 by default
4203        break;
4204
4205    case ALT_CLK_PERIPHERAL_PLL:
4206        if (alt_clk_pll_is_bypassed(ALT_CLK_PERIPHERAL_PLL) == ALT_E_TRUE)
4207        {
4208            temp = ALT_CLKMGR_PERPLL_VCO_PSRC_GET(alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR));
4209            if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC1)
4210            {
4211                temp = alt_ext_clk_paramblok.clkosc1.freqcur;
4212                ret = ALT_E_SUCCESS;
4213            }
4214            else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_EOSC2)
4215            {
4216                temp = alt_ext_clk_paramblok.clkosc2.freqcur;
4217                ret = ALT_E_SUCCESS;
4218            }
4219            else if (temp == ALT_CLKMGR_PERPLL_VCO_PSRC_E_F2S_PERIPH_REF)
4220            {
4221                temp = alt_ext_clk_paramblok.periph.freqcur;
4222                ret = ALT_E_SUCCESS;
4223            }
4224            else
4225            {
4226                ret = ALT_E_ERROR;
4227            }
4228        }
4229        else
4230        {
4231            ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4232        }
4233        numer = (uint64_t) temp;
4234        // denom = 1 by default
4235        break;
4236
4237    case ALT_CLK_SDRAM_PLL:
4238        if (alt_clk_pll_is_bypassed(ALT_CLK_SDRAM_PLL) == ALT_E_TRUE)
4239        {
4240            temp = ALT_CLKMGR_SDRPLL_VCO_SSRC_GET(alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR));
4241            if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC1)
4242            {
4243                temp = alt_ext_clk_paramblok.clkosc1.freqcur;
4244                ret = ALT_E_SUCCESS;
4245            }
4246            else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_EOSC2)
4247            {
4248                temp = alt_ext_clk_paramblok.clkosc2.freqcur;
4249                ret = ALT_E_SUCCESS;
4250            }
4251            else if (temp == ALT_CLKMGR_SDRPLL_VCO_SSRC_E_F2S_SDRAM_REF)
4252            {
4253                temp = alt_ext_clk_paramblok.sdram.freqcur;
4254                ret = ALT_E_SUCCESS;
4255            }
4256            else
4257            {
4258                ret = ALT_E_ERROR;
4259            }
4260        }
4261        else
4262        {
4263            ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
4264        }
4265        numer = (uint64_t) temp;
4266        // denom = 1 by default
4267        break;
4268
4269        /////
4270
4271        // Main Clock Group
4272    case ALT_CLK_MAIN_PLL_C0:
4273    case ALT_CLK_MAIN_PLL_C1:
4274    case ALT_CLK_MAIN_PLL_C2:
4275    case ALT_CLK_MAIN_PLL_C3:
4276    case ALT_CLK_MAIN_PLL_C4:
4277    case ALT_CLK_MAIN_PLL_C5:
4278        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4279        if (ret == ALT_E_SUCCESS)
4280        {
4281            numer = (uint64_t) temp;
4282            ret = alt_clk_divider_get(clk, &temp);
4283            denom = (uint64_t) temp;
4284        }
4285        break;
4286
4287    case ALT_CLK_MPU:
4288        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4289        if (ret == ALT_E_SUCCESS)
4290        {
4291            numer = (uint64_t) temp;
4292            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C0, &temp);
4293            denom = (uint64_t) temp;
4294        }
4295        break;
4296
4297    case ALT_CLK_MPU_PERIPH:
4298        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4299        if (ret == ALT_E_SUCCESS)
4300        {
4301            numer = (uint64_t) temp;
4302            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C0, &temp);
4303        }
4304        if (ret == ALT_E_SUCCESS)
4305        {
4306            denom = (uint64_t) temp;
4307            ret = alt_clk_divider_get(ALT_CLK_MPU_PERIPH, &temp);
4308            denom = denom * (uint64_t) temp;
4309        }
4310        break;
4311
4312    case ALT_CLK_MPU_L2_RAM:
4313        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4314        if (ret == ALT_E_SUCCESS)
4315        {
4316            numer = (uint64_t) temp;
4317            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C0, &temp);
4318        }
4319        if (ret == ALT_E_SUCCESS)
4320        {
4321            denom = (uint64_t) temp;
4322            ret = alt_clk_divider_get(ALT_CLK_MPU_L2_RAM, &temp);
4323            denom = denom * (uint64_t) temp;
4324        }
4325        break;
4326
4327    case ALT_CLK_L4_MAIN:
4328    case ALT_CLK_L3_MAIN:
4329        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4330        if (ret == ALT_E_SUCCESS)
4331        {
4332            numer = (uint64_t) temp;
4333            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
4334            denom = (uint64_t) temp;
4335        }
4336        break;
4337
4338    case ALT_CLK_L3_MP:
4339        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4340        if (ret == ALT_E_SUCCESS)
4341        {
4342            numer = (uint64_t) temp;
4343            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
4344        }
4345        if (ret == ALT_E_SUCCESS)
4346        {
4347            denom = (uint64_t) temp;
4348            ret = alt_clk_divider_get(ALT_CLK_L3_MP, &temp);
4349            denom = denom * (uint64_t) temp;
4350        }
4351        break;
4352
4353    case ALT_CLK_L3_SP:
4354        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4355        if (ret == ALT_E_SUCCESS)
4356        {
4357            numer = (uint64_t) temp;
4358            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
4359        }
4360        if (ret == ALT_E_SUCCESS)
4361        {
4362            denom = (uint64_t) temp;
4363            ret = alt_clk_divider_get(ALT_CLK_L3_MP, &temp);
4364        }
4365        if (ret == ALT_E_SUCCESS)
4366        {
4367            denom = denom * (uint64_t) temp;
4368            ret = alt_clk_divider_get(ALT_CLK_L3_SP, &temp);
4369            denom = denom * (uint64_t) temp;
4370        }
4371        break;
4372
4373    case ALT_CLK_L4_MP:
4374        ret = alt_clk_divider_get(ALT_CLK_L4_MP, &temp);
4375        if (ret == ALT_E_SUCCESS)
4376        {
4377            denom = (uint64_t) temp;
4378            temp = ALT_CLKMGR_MAINPLL_L4SRC_L4MP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR));
4379            if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_MAINPLL)
4380            {
4381                ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4382                if (ret == ALT_E_SUCCESS)
4383                {
4384                    numer = (uint64_t) temp;
4385                    ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
4386                    denom = denom * (uint64_t) temp;        // no real harm if temp is garbage data
4387                }
4388            }
4389            else if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4MP_E_PERIPHPLL)
4390            {
4391                ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4392                if (ret == ALT_E_SUCCESS)
4393                {
4394                    numer = (uint64_t) temp;
4395                    ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
4396                    denom = denom * (uint64_t) temp;
4397                }
4398            }
4399        }
4400        break;
4401
4402    case ALT_CLK_L4_SP:
4403        ret = alt_clk_divider_get(ALT_CLK_L4_SP, &temp);
4404        if (ret == ALT_E_SUCCESS)
4405        {
4406            denom = (uint64_t) temp;
4407            temp = ALT_CLKMGR_MAINPLL_L4SRC_L4SP_GET(alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR));
4408            if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_MAINPLL)
4409            {
4410                ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4411                if (ret == ALT_E_SUCCESS)
4412                {
4413                    numer = (uint64_t) temp;
4414                    ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C1, &temp);
4415                    denom = denom * (uint64_t) temp;
4416                }
4417            }
4418            else if (temp == ALT_CLKMGR_MAINPLL_L4SRC_L4SP_E_PERIPHPLL)         // periph_base_clk
4419            {
4420                ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4421                if (ret == ALT_E_SUCCESS)
4422                {
4423                    numer = (uint64_t) temp;
4424                    ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
4425                    denom = denom * (uint64_t) temp;
4426                }
4427            }
4428        }
4429        break;
4430
4431    case ALT_CLK_DBG_BASE:
4432    case ALT_CLK_DBG_TIMER:
4433        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4434        if (ret == ALT_E_SUCCESS)
4435        {
4436            numer = (uint64_t) temp;
4437            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
4438            denom = (uint64_t) temp;
4439        }
4440        break;
4441
4442    case ALT_CLK_DBG_AT:
4443        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4444        if (ret == ALT_E_SUCCESS)
4445        {
4446            numer = (uint64_t) temp;
4447            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
4448        }
4449        if (ret == ALT_E_SUCCESS)
4450        {
4451            denom = (uint64_t) temp;
4452            ret = alt_clk_divider_get(ALT_CLK_DBG_AT, &temp);
4453            denom = denom * (uint64_t) temp;
4454        }
4455        break;
4456
4457    case ALT_CLK_DBG:
4458        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4459        if (ret == ALT_E_SUCCESS)
4460        {
4461            numer = (uint64_t) temp;
4462            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
4463        }
4464        if (ret == ALT_E_SUCCESS)
4465        {
4466            denom = (uint64_t) temp;
4467            ret = alt_clk_divider_get(ALT_CLK_DBG_AT, &temp);
4468        }
4469        if (ret == ALT_E_SUCCESS)
4470        {
4471            denom = denom * (uint64_t) temp;
4472            ret = alt_clk_divider_get(ALT_CLK_DBG, &temp);
4473            denom = denom * (uint64_t) temp;
4474        }
4475        break;
4476
4477    case ALT_CLK_DBG_TRACE:
4478        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4479        if (ret == ALT_E_SUCCESS)
4480        {
4481            numer = (uint64_t) temp;
4482            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C2, &temp);
4483        }
4484        if (ret == ALT_E_SUCCESS)
4485        {
4486            denom = (uint64_t) temp;
4487            ret = alt_clk_divider_get(ALT_CLK_DBG_TRACE, &temp);
4488            denom = denom * (uint64_t) temp;
4489        }
4490        break;
4491
4492    case ALT_CLK_MAIN_QSPI:
4493        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4494        if (ret == ALT_E_SUCCESS)
4495        {
4496            numer = (uint64_t) temp;
4497            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C3, &temp);
4498            denom = (uint64_t) temp;
4499        }
4500        break;
4501
4502    case ALT_CLK_MAIN_NAND_SDMMC:
4503        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4504        if (ret == ALT_E_SUCCESS)
4505        {
4506            numer = (uint64_t) temp;
4507            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C4, &temp);
4508            denom = (uint64_t) temp;
4509        }
4510        break;
4511
4512    case ALT_CLK_CFG:
4513    case ALT_CLK_H2F_USER0:
4514        ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4515        if (ret == ALT_E_SUCCESS)
4516        {
4517            numer = (uint64_t) temp;
4518            ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C5, &temp);
4519            denom = (uint64_t) temp;
4520        }
4521        break;
4522
4523        /////
4524
4525        // Peripheral Clock Group
4526    case ALT_CLK_PERIPHERAL_PLL_C0:
4527    case ALT_CLK_PERIPHERAL_PLL_C1:
4528    case ALT_CLK_PERIPHERAL_PLL_C2:
4529    case ALT_CLK_PERIPHERAL_PLL_C3:
4530    case ALT_CLK_PERIPHERAL_PLL_C4:
4531    case ALT_CLK_PERIPHERAL_PLL_C5:
4532        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4533        if (ret == ALT_E_SUCCESS)
4534        {
4535            numer = (uint64_t) temp;
4536            ret = alt_clk_divider_get(clk, &temp);
4537            denom = (uint64_t) temp;
4538        }
4539        break;
4540
4541    case ALT_CLK_EMAC0:
4542        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4543        if (ret == ALT_E_SUCCESS)
4544        {
4545            numer = (uint64_t) temp;
4546            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C0, &temp);
4547            denom = (uint64_t) temp;
4548        }
4549        break;
4550
4551    case ALT_CLK_EMAC1:
4552        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4553        if (ret == ALT_E_SUCCESS)
4554        {
4555            numer = (uint64_t) temp;
4556            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C1, &temp);
4557            denom = (uint64_t) temp;
4558        }
4559        break;
4560
4561    case ALT_CLK_USB_MP:
4562        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4563        if (ret == ALT_E_SUCCESS)
4564        {
4565            numer = (uint64_t) temp;
4566            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
4567            if (ret == ALT_E_SUCCESS)
4568            {
4569                denom = (uint64_t) temp;
4570                ret = alt_clk_divider_get(ALT_CLK_USB_MP, &temp);
4571                denom = denom * (uint64_t) temp;
4572            }
4573        }
4574        break;
4575
4576    case ALT_CLK_SPI_M:
4577        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4578        if (ret == ALT_E_SUCCESS)
4579        {
4580            numer = (uint64_t) temp;
4581            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
4582        }
4583        if (ret == ALT_E_SUCCESS)
4584        {
4585            denom = (uint64_t) temp;
4586            ret = alt_clk_divider_get(ALT_CLK_SPI_M, &temp);
4587            denom = denom * (uint64_t) temp;
4588        }
4589        break;
4590
4591    case ALT_CLK_CAN0:
4592        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4593        if (ret == ALT_E_SUCCESS)
4594        {
4595            numer = (uint64_t) temp;
4596            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
4597        }
4598        if (ret == ALT_E_SUCCESS)
4599        {
4600            denom = (uint64_t) temp;
4601            ret = alt_clk_divider_get(ALT_CLK_CAN0, &temp);
4602            denom = denom * (uint64_t) temp;
4603        }
4604        break;
4605
4606    case ALT_CLK_CAN1:
4607        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4608        if (ret == ALT_E_SUCCESS)
4609        {
4610            numer = (uint64_t) temp;
4611            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
4612        }
4613        if (ret == ALT_E_SUCCESS)
4614        {
4615            denom = (uint64_t) temp;
4616            ret = alt_clk_divider_get(ALT_CLK_CAN1, &temp);
4617            denom = denom * (uint64_t) temp;
4618        }
4619        break;
4620
4621    case ALT_CLK_GPIO_DB:
4622        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4623        if (ret == ALT_E_SUCCESS)
4624        {
4625            numer = (uint64_t) temp;
4626            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C4, &temp);
4627        }
4628        if (ret == ALT_E_SUCCESS)
4629        {
4630            denom = (uint64_t) temp;
4631            ret = alt_clk_divider_get(ALT_CLK_GPIO_DB, &temp);
4632            denom = denom * (uint64_t) temp;
4633        }
4634        break;
4635
4636    case ALT_CLK_H2F_USER1:
4637        ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4638        if (ret == ALT_E_SUCCESS)
4639        {
4640            numer = (uint64_t) temp;
4641            ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C5, &temp);
4642            denom = (uint64_t) temp;
4643        }
4644        break;
4645
4646        /* Clocks That Can Switch Between Different Clock Groups */
4647    case ALT_CLK_SDMMC:
4648        temp = ALT_CLKMGR_PERPLL_SRC_SDMMC_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
4649        if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_F2S_PERIPH_REF_CLK)
4650        {
4651            numer = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
4652            // denom = 1 by default
4653            ret = ALT_E_SUCCESS;
4654        }
4655        else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_MAIN_NAND_CLK)
4656        {
4657            ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4658            if (ret == ALT_E_SUCCESS)
4659            {
4660                numer = (uint64_t) temp;
4661                ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C4, &temp);
4662                denom = (uint64_t) temp;
4663            }
4664        }
4665        else if (temp == ALT_CLKMGR_PERPLL_SRC_SDMMC_E_PERIPH_NAND_CLK)
4666        {
4667            ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4668            if (ret == ALT_E_SUCCESS)
4669            {
4670                numer = (uint64_t) temp;
4671                ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C3, &temp);
4672                denom = (uint64_t) temp;
4673            }
4674        }
4675        else
4676        {
4677            ret = ALT_E_ERROR;
4678        }
4679        break;
4680
4681    case ALT_CLK_NAND:
4682        denom = 4;
4683        // the absence of a break statement here is not a mistake
4684    case ALT_CLK_NAND_X:
4685        temp = ALT_CLKMGR_PERPLL_SRC_NAND_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
4686        if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_F2S_PERIPH_REF_CLK)
4687        {
4688            numer = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
4689            // denom = 1 or 4 by default;
4690            ret = ALT_E_SUCCESS;
4691        }
4692        else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_MAIN_NAND_CLK)
4693        {
4694            ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4695            if (ret == ALT_E_SUCCESS)
4696            {
4697                numer = (uint64_t) temp;
4698                ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C4, &temp);
4699                denom = denom * (uint64_t) temp;
4700            }
4701        }
4702        else if (temp == ALT_CLKMGR_PERPLL_SRC_NAND_E_PERIPH_NAND_CLK)
4703        {
4704            ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4705            if (ret == ALT_E_SUCCESS)
4706            {
4707                numer = (uint64_t) temp;
4708                ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C3, &temp);
4709                denom = denom * (uint64_t) temp;
4710            }
4711        }
4712        else
4713        {
4714            ret = ALT_E_ERROR;
4715        }
4716        break;
4717
4718    case ALT_CLK_QSPI:
4719        temp = ALT_CLKMGR_PERPLL_SRC_QSPI_GET(alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR));
4720        if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_F2S_PERIPH_REF_CLK)
4721        {
4722            numer = (uint64_t) alt_ext_clk_paramblok.periph.freqcur;
4723            // denom = 1 by default;
4724            ret = ALT_E_SUCCESS;
4725        }
4726        else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_MAIN_QSPI_CLK)
4727        {
4728            ret = alt_clk_pll_vco_freq_get(ALT_CLK_MAIN_PLL, &temp);
4729            if (ret == ALT_E_SUCCESS)
4730            {
4731                numer = (uint64_t) temp;
4732                ret = alt_clk_divider_get(ALT_CLK_MAIN_PLL_C3, &temp);
4733                denom = (uint64_t) temp;
4734            }
4735        }
4736        else if (temp == ALT_CLKMGR_PERPLL_SRC_QSPI_E_PERIPH_QSPI_CLK)
4737        {
4738            ret = alt_clk_pll_vco_freq_get(ALT_CLK_PERIPHERAL_PLL, &temp);
4739            if (ret == ALT_E_SUCCESS)
4740            {
4741                numer = (uint64_t) temp;
4742                ret = alt_clk_divider_get(ALT_CLK_PERIPHERAL_PLL_C2, &temp);
4743                denom = (uint64_t) temp;
4744            }
4745        }
4746        else
4747        {
4748            ret = ALT_E_ERROR;
4749        }
4750        break;
4751
4752        /////
4753
4754        // SDRAM Clock Group
4755    case ALT_CLK_SDRAM_PLL_C0:
4756    case ALT_CLK_DDR_DQS:
4757        ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
4758        if (ret == ALT_E_SUCCESS)
4759        {
4760            numer = (uint64_t) temp;
4761            ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C0, &temp);
4762            denom = (uint64_t) temp;
4763        }
4764        break;
4765
4766    case ALT_CLK_SDRAM_PLL_C1:
4767    case ALT_CLK_DDR_2X_DQS:
4768        ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
4769        if (ret == ALT_E_SUCCESS)
4770        {
4771            numer = (uint64_t) temp;
4772            ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C1, &temp);
4773            denom = (uint64_t) temp;
4774        }
4775        break;
4776
4777    case ALT_CLK_SDRAM_PLL_C2:
4778    case ALT_CLK_DDR_DQ:
4779        ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
4780        if (ret == ALT_E_SUCCESS)
4781        {
4782            numer = (uint64_t) temp;
4783            ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C2, &temp);
4784            denom = (uint64_t) temp;
4785        }
4786        break;
4787
4788    case ALT_CLK_SDRAM_PLL_C5:
4789    case ALT_CLK_H2F_USER2:
4790        ret = alt_clk_pll_vco_freq_get(ALT_CLK_SDRAM_PLL, &temp);
4791        if (ret == ALT_E_SUCCESS)
4792        {
4793            numer = (uint64_t) temp;
4794            ret = alt_clk_divider_get(ALT_CLK_SDRAM_PLL_C5, &temp);
4795            denom = (uint64_t) temp;
4796        }
4797        break;
4798
4799    default:
4800        ret = ALT_E_BAD_ARG;
4801        break;
4802
4803    }   // end of switch-case construct
4804
4805    if (ret == ALT_E_SUCCESS)
4806    {
4807        // will not get here if none of above cases match
4808        if (denom > 0)
4809        {
4810            numer /= denom;
4811            if (numer <= UINT32_MAX)
4812            {
4813                *freq = (uint32_t) numer;
4814            }
4815            else
4816            {
4817                ret = ALT_E_ERROR;
4818            }
4819        }
4820        else
4821        {
4822            ret = ALT_E_ERROR;
4823        }
4824    }
4825
4826    return ret;
4827}
4828
4829//
4830// alt_clk_irq_disable() disables one or more of the lock status conditions as
4831// contributors to the clkmgr_IRQ interrupt signal state.
4832//
4833ALT_STATUS_CODE alt_clk_irq_disable(ALT_CLK_PLL_LOCK_STATUS_t lock_stat_mask)
4834{
4835    if (!(lock_stat_mask & ALT_CLK_MGR_PLL_LOCK_BITS))
4836    {
4837        alt_clrbits_word(ALT_CLKMGR_INTREN_ADDR, lock_stat_mask);
4838        return ALT_E_SUCCESS;
4839    }
4840    else
4841    {
4842        return ALT_E_BAD_ARG;
4843    }
4844}
4845
4846//
4847// alt_clk_irq_enable() enables one or more of the lock status conditions as
4848// contributors to the clkmgr_IRQ interrupt signal state.
4849//
4850ALT_STATUS_CODE alt_clk_irq_enable(ALT_CLK_PLL_LOCK_STATUS_t lock_stat_mask)
4851{
4852    if (!(lock_stat_mask & ALT_CLK_MGR_PLL_LOCK_BITS))
4853    {
4854        alt_setbits_word(ALT_CLKMGR_INTREN_ADDR, lock_stat_mask);
4855        return ALT_E_SUCCESS;
4856    }
4857    else
4858    {
4859        return ALT_E_BAD_ARG;
4860    }
4861}
4862
4863/////
4864
4865//
4866// alt_clk_group_cfg_raw_get() gets the raw configuration state of the designated
4867// clock group.
4868//
4869ALT_STATUS_CODE alt_clk_group_cfg_raw_get(ALT_CLK_GRP_t clk_group,
4870                                          ALT_CLK_GROUP_RAW_CFG_t * clk_group_raw_cfg)
4871{
4872    clk_group_raw_cfg->verid     = alt_read_word(ALT_SYSMGR_SILICONID1_ADDR);
4873    clk_group_raw_cfg->siliid2   = alt_read_word(ALT_SYSMGR_SILICONID2_ADDR);
4874    clk_group_raw_cfg->clkgrpsel = clk_group;
4875
4876    if (clk_group == ALT_MAIN_PLL_CLK_GRP)
4877    {
4878        // Main PLL VCO register
4879        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.vco = alt_read_word(ALT_CLKMGR_MAINPLL_VCO_ADDR);
4880
4881        // Main PLL Misc register
4882        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.misc = alt_read_word(ALT_CLKMGR_MAINPLL_MISC_ADDR);
4883
4884        // Main PLL C0-C5 Counter registers
4885        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mpuclk = alt_read_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR);
4886        // doing these as 32-bit reads and writes avoids unnecessary masking operations
4887
4888        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainclk          = alt_read_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR);
4889        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgatclk         = alt_read_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR);
4890        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainqspiclk      = alt_read_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR);
4891        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainnandsdmmcclk = alt_read_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR);
4892        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.cfgs2fuser0clk   = alt_read_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR);
4893
4894        // Main PLL Enable register
4895        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.en = alt_read_word(ALT_CLKMGR_MAINPLL_EN_ADDR);
4896
4897        // Main PLL Maindiv register
4898        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.maindiv = alt_read_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR);
4899
4900        // Main PLL Debugdiv register
4901        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgdiv = alt_read_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR);
4902
4903        // Main PLL Tracediv register
4904        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.tracediv = alt_read_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR);
4905
4906        // Main PLL L4 Source register
4907        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.l4src = alt_read_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR);
4908
4909        // Main PLL Status register
4910        clk_group_raw_cfg->clkgrp.mainpllgrp.raw.stat = alt_read_word(ALT_CLKMGR_MAINPLL_STAT_ADDR);
4911        // clkgrp.mainpllgrp.stat.outresetack is defined in the ALT_CLKMGR_MAINPLL_STAT_s declaration
4912        // as a const but alt_indwrite_word() overrides that restriction.
4913
4914        // padding ...
4915        clk_group_raw_cfg->clkgrp.mainpllgrp.raw._pad_0x38_0x40[0] = 0;
4916        clk_group_raw_cfg->clkgrp.mainpllgrp.raw._pad_0x38_0x40[1] = 0;
4917
4918        return ALT_E_SUCCESS;
4919    }
4920    else if (clk_group == ALT_PERIPH_PLL_CLK_GRP)
4921    {
4922        // Peripheral PLL VCO register
4923        clk_group_raw_cfg->clkgrp.perpllgrp.raw.vco = alt_read_word(ALT_CLKMGR_PERPLL_VCO_ADDR);
4924
4925        // Peripheral PLL Misc register
4926        clk_group_raw_cfg->clkgrp.perpllgrp.raw.misc = alt_read_word(ALT_CLKMGR_PERPLL_MISC_ADDR);
4927
4928        // Peripheral PLL C0-C5 Counters
4929        clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac0clk = alt_read_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR);
4930        // doing these as 32-bit reads and writes avoids unnecessary masking operations
4931
4932        clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac1clk        = alt_read_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR);
4933        clk_group_raw_cfg->clkgrp.perpllgrp.raw.perqspiclk      = alt_read_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR);
4934        clk_group_raw_cfg->clkgrp.perpllgrp.raw.pernandsdmmcclk = alt_read_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR);
4935        clk_group_raw_cfg->clkgrp.perpllgrp.raw.perbaseclk      = alt_read_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR);
4936        clk_group_raw_cfg->clkgrp.perpllgrp.raw.s2fuser1clk     = alt_read_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR);
4937
4938        // Peripheral PLL Enable register
4939        clk_group_raw_cfg->clkgrp.perpllgrp.raw.en = alt_read_word(ALT_CLKMGR_PERPLL_EN_ADDR);
4940
4941        // Peripheral PLL Divider register
4942        clk_group_raw_cfg->clkgrp.perpllgrp.raw.div = alt_read_word(ALT_CLKMGR_PERPLL_DIV_ADDR);
4943
4944        // Peripheral PLL GPIO Divider register
4945        clk_group_raw_cfg->clkgrp.perpllgrp.raw.gpiodiv = alt_read_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR);
4946
4947        // Peripheral PLL Source register
4948        clk_group_raw_cfg->clkgrp.perpllgrp.raw.src = alt_read_word(ALT_CLKMGR_PERPLL_SRC_ADDR);
4949
4950        // Peripheral PLL Status register
4951        clk_group_raw_cfg->clkgrp.perpllgrp.raw.stat = alt_read_word(ALT_CLKMGR_PERPLL_STAT_ADDR);
4952
4953        // padding ...
4954        clk_group_raw_cfg->clkgrp.perpllgrp.raw._pad_0x34_0x40[0] = 0;
4955        clk_group_raw_cfg->clkgrp.perpllgrp.raw._pad_0x34_0x40[1] = 0;
4956        clk_group_raw_cfg->clkgrp.perpllgrp.raw._pad_0x34_0x40[2] = 0;
4957
4958        return ALT_E_SUCCESS;
4959    }
4960    else if (clk_group == ALT_SDRAM_PLL_CLK_GRP)
4961    {
4962        // SDRAM PLL VCO register
4963        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.vco = alt_read_word(ALT_CLKMGR_SDRPLL_VCO_ADDR);
4964
4965        // SDRAM PLL Control register
4966        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ctrl = alt_read_word(ALT_CLKMGR_SDRPLL_CTL_ADDR);
4967
4968        // SDRAM PLL C0-C2 & C5 Counters
4969        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqsclk = alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR);
4970        // doing these as 32-bit reads and writes avoids unnecessary masking operations
4971
4972        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddr2xdqsclk = alt_read_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR);
4973        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqclk    = alt_read_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR);
4974        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.s2fuser2clk = alt_read_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR);
4975
4976        // SDRAM PLL Enable register
4977        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.en = alt_read_word(ALT_CLKMGR_SDRPLL_EN_ADDR);
4978
4979        // SDRAM PLL Status register
4980        clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.stat = alt_read_word(ALT_CLKMGR_SDRPLL_STAT_ADDR);
4981
4982        return ALT_E_SUCCESS;
4983    }
4984    else
4985    {
4986        return ALT_E_BAD_ARG;
4987    }
4988}
4989
4990//
4991// alt_clk_group_cfg_raw_set() sets the clock group configuration.
4992//
4993ALT_STATUS_CODE alt_clk_group_cfg_raw_set(const ALT_CLK_GROUP_RAW_CFG_t * clk_group_raw_cfg)
4994{
4995    // test for matching silicon ID, but not for matching silicon revision number
4996    if (ALT_SYSMGR_SILICONID1_ID_GET(alt_read_word(ALT_SYSMGR_SILICONID1_ADDR)) !=
4997        ALT_SYSMGR_SILICONID1_ID_GET(clk_group_raw_cfg->verid))
4998    {
4999        return ALT_E_BAD_VERSION;
5000    }
5001
5002    // get the PLL ID
5003    ALT_CLK_GRP_t clk_group = clk_group_raw_cfg->clkgrpsel;
5004    ALT_CLK_t     pll;
5005
5006    if      (clk_group == ALT_MAIN_PLL_CLK_GRP)   { pll = ALT_CLK_MAIN_PLL; }
5007    else if (clk_group == ALT_PERIPH_PLL_CLK_GRP) { pll = ALT_CLK_PERIPHERAL_PLL; }
5008    else if (clk_group == ALT_SDRAM_PLL_CLK_GRP)  { pll = ALT_CLK_SDRAM_PLL; }
5009    else
5010    {
5011        return ALT_E_ERROR;
5012    }
5013
5014    ALT_STATUS_CODE status = ALT_E_SUCCESS;
5015
5016    // if the PLL isn't in bypass mode, put it in bypass mode
5017    bool byp = false;
5018    if (alt_clk_pll_is_bypassed(pll) == ALT_E_FALSE)
5019    {
5020        status = alt_clk_pll_bypass_enable(pll, false);
5021        if (status != ALT_E_SUCCESS)
5022        {
5023            return status;
5024        }
5025
5026        byp = true;
5027    }
5028
5029    // now write the values in the ALT_CLK_GROUP_RAW_CFG_t structure to the registers
5030    if (clk_group == ALT_MAIN_PLL_CLK_GRP)
5031    {
5032        // Main PLL VCO register
5033        alt_write_word(ALT_CLKMGR_MAINPLL_VCO_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.vco &
5034                       ALT_CLKMGR_MAINPLL_VCO_OUTRSTALL_CLR_MSK & ALT_CLKMGR_MAINPLL_VCO_OUTRST_CLR_MSK);
5035        // the outreset and outresetall bits were probably clear when the
5036        // state was saved, but make sure they're clear now
5037
5038        // Main PLL Misc register
5039        alt_write_word(ALT_CLKMGR_MAINPLL_MISC_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.misc);
5040
5041        // Main PLL C0-C5 Counter registers
5042        alt_write_word(ALT_CLKMGR_MAINPLL_MPUCLK_ADDR,           clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mpuclk);
5043        alt_write_word(ALT_CLKMGR_MAINPLL_MAINCLK_ADDR,          clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainclk);
5044        alt_write_word(ALT_CLKMGR_MAINPLL_DBGATCLK_ADDR,         clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgatclk);
5045        alt_write_word(ALT_CLKMGR_MAINPLL_MAINQSPICLK_ADDR,      clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainqspiclk);
5046        alt_write_word(ALT_CLKMGR_MAINPLL_MAINNANDSDMMCCLK_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.mainnandsdmmcclk);
5047        alt_write_word(ALT_CLKMGR_MAINPLL_CFGS2FUSER0CLK_ADDR,   clk_group_raw_cfg->clkgrp.mainpllgrp.raw.cfgs2fuser0clk);
5048
5049        // Main PLL Counter Enable register
5050        alt_write_word(ALT_CLKMGR_MAINPLL_EN_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.en);
5051
5052        // Main PLL Maindiv register
5053        alt_write_word(ALT_CLKMGR_MAINPLL_MAINDIV_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.maindiv);
5054
5055        // Main PLL Debugdiv register
5056        alt_write_word(ALT_CLKMGR_MAINPLL_DBGDIV_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.dbgdiv);
5057
5058        // Main PLL Tracediv register
5059        alt_write_word(ALT_CLKMGR_MAINPLL_TRACEDIV_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.tracediv);
5060
5061        // Main PLL L4 Source register
5062        alt_write_word(ALT_CLKMGR_MAINPLL_L4SRC_ADDR, clk_group_raw_cfg->clkgrp.mainpllgrp.raw.l4src);
5063    }
5064    else if (clk_group == ALT_PERIPH_PLL_CLK_GRP)
5065    {
5066        // Peripheral PLL VCO register
5067        alt_write_word(ALT_CLKMGR_PERPLL_VCO_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.vco &
5068                       ALT_CLKMGR_PERPLL_VCO_OUTRST_CLR_MSK & ALT_CLKMGR_PERPLL_VCO_OUTRSTALL_CLR_MSK);
5069        // the outreset and outresetall bits were probably clear when the
5070        // state was saved, but make sure they're clear now
5071
5072        // Peripheral PLL Misc register
5073        alt_write_word(ALT_CLKMGR_PERPLL_MISC_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.misc);
5074
5075        // Peripheral PLL C0-C5 Counters
5076        alt_write_word(ALT_CLKMGR_PERPLL_EMAC0CLK_ADDR,        clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac0clk);
5077        alt_write_word(ALT_CLKMGR_PERPLL_EMAC1CLK_ADDR,        clk_group_raw_cfg->clkgrp.perpllgrp.raw.emac1clk);
5078        alt_write_word(ALT_CLKMGR_PERPLL_PERQSPICLK_ADDR,      clk_group_raw_cfg->clkgrp.perpllgrp.raw.perqspiclk);
5079        alt_write_word(ALT_CLKMGR_PERPLL_PERNANDSDMMCCLK_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.pernandsdmmcclk);
5080        alt_write_word(ALT_CLKMGR_PERPLL_PERBASECLK_ADDR,      clk_group_raw_cfg->clkgrp.perpllgrp.raw.perbaseclk);
5081        alt_write_word(ALT_CLKMGR_PERPLL_S2FUSER1CLK_ADDR,     clk_group_raw_cfg->clkgrp.perpllgrp.raw.s2fuser1clk);
5082
5083        // Peripheral PLL Counter Enable register
5084        alt_write_word(ALT_CLKMGR_PERPLL_EN_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.en);
5085
5086        // Peripheral PLL Divider register
5087        alt_write_word(ALT_CLKMGR_PERPLL_DIV_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.div);
5088
5089        // Peripheral PLL GPIO Divider register
5090        alt_write_word(ALT_CLKMGR_PERPLL_GPIODIV_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.gpiodiv);
5091
5092        // Peripheral PLL Source register
5093        alt_write_word(ALT_CLKMGR_PERPLL_SRC_ADDR, clk_group_raw_cfg->clkgrp.perpllgrp.raw.src);
5094    }
5095    else if (clk_group == ALT_SDRAM_PLL_CLK_GRP)
5096    {
5097        // SDRAM PLL VCO register
5098        alt_write_word(ALT_CLKMGR_SDRPLL_VCO_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.vco &
5099                       ALT_CLKMGR_SDRPLL_VCO_OUTRST_CLR_MSK & ALT_CLKMGR_SDRPLL_VCO_OUTRSTALL_CLR_MSK);
5100        // the outreset and outresetall bits were probably clear when the
5101        // state was saved, but make sure they're clear now
5102
5103        // SDRAM PLL Control register
5104        alt_write_word(ALT_CLKMGR_SDRPLL_CTL_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ctrl);
5105
5106        // SDRAM PLL C0-C2 & C5 Counters
5107        alt_write_word(ALT_CLKMGR_SDRPLL_DDRDQSCLK_ADDR,   clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqsclk);
5108        alt_write_word(ALT_CLKMGR_SDRPLL_DDR2XDQSCLK_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddr2xdqsclk);
5109        alt_write_word(ALT_CLKMGR_SDRPLL_DDRDQCLK_ADDR,    clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.ddrdqclk);
5110        alt_write_word(ALT_CLKMGR_SDRPLL_S2FUSER2CLK_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.s2fuser2clk);
5111
5112        // SDRAM PLL Counter Enable register
5113        alt_write_word(ALT_CLKMGR_SDRPLL_EN_ADDR, clk_group_raw_cfg->clkgrp.sdrpllgrp.raw.en);
5114    }
5115
5116    // if PLL was not bypassed before, restore that state
5117    if (byp)
5118    {
5119        status = alt_clk_pll_bypass_disable(pll);
5120    }
5121
5122    return status;
5123}
5124
5125//
5126// alt_clk_id_to_string() converts a clock ID to a text string.
5127//
5128ALT_STATUS_CODE alt_clk_id_to_string(ALT_CLK_t clk_id, char * output, size_t size)
5129{
5130    char * name = NULL;
5131
5132    switch (clk_id)
5133    {
5134    case ALT_CLK_IN_PIN_OSC1:
5135        name =  "IN_PIN_OSC1";
5136        break;
5137    case ALT_CLK_IN_PIN_OSC2:
5138        name =  "IN_PIN_OSC2";
5139        break;
5140
5141        // FPGA Clock Sources External to HPS
5142    case ALT_CLK_F2H_PERIPH_REF:
5143        name =  "F2H_PERIPH_REF";
5144        break;
5145    case ALT_CLK_F2H_SDRAM_REF:
5146        name =  "F2H_SDRAM_REF";
5147        break;
5148
5149        // Other Clock Sources External to HPS
5150    case ALT_CLK_IN_PIN_JTAG:
5151        name =  "IN_PIN_JTAG";
5152        break;
5153    case ALT_CLK_IN_PIN_ULPI0:
5154        name =  "IN_PIN_ULPI0";
5155        break;
5156    case ALT_CLK_IN_PIN_ULPI1:
5157        name =  "IN_PIN_ULPI1";
5158        break;
5159    case ALT_CLK_IN_PIN_EMAC0_RX:
5160        name =  "IN_PIN_EMAC0_RX";
5161        break;
5162    case ALT_CLK_IN_PIN_EMAC1_RX:
5163        name =  "IN_PIN_EMAC1_RX";
5164        break;
5165
5166        // PLLs
5167    case ALT_CLK_MAIN_PLL:
5168        name =  "MAIN_PLL";
5169        break;
5170    case ALT_CLK_PERIPHERAL_PLL:
5171        name =  "PERIPHERAL_PLL";
5172        break;
5173    case ALT_CLK_SDRAM_PLL:
5174        name =  "SDRAM_PLL";
5175        break;
5176
5177        // OSC1 Clock Group - The OSC1 clock group contains those clocks which are derived
5178        // directly from the osc_clk_1_HPS pin
5179    case ALT_CLK_OSC1:
5180        name =  "OSC1";
5181        break;
5182
5183        // Main Clock Group - The following clocks are derived from the Main PLL.
5184    case ALT_CLK_MAIN_PLL_C0:
5185        name =  "MAIN_PLL_C0";
5186        break;
5187    case ALT_CLK_MAIN_PLL_C1:
5188        name =  "MAIN_PLL_C1";
5189        break;
5190    case ALT_CLK_MAIN_PLL_C2:
5191        name =  "MAIN_PLL_C2";
5192        break;
5193    case ALT_CLK_MAIN_PLL_C3:
5194        name =  "MAIN_PLL_C3";
5195        break;
5196    case ALT_CLK_MAIN_PLL_C4:
5197        name =  "MAIN_PLL_C4";
5198        break;
5199    case ALT_CLK_MAIN_PLL_C5:
5200        name =  "MAIN_PLL_C5";
5201        break;
5202    case ALT_CLK_MPU:
5203        name =  "MPU";
5204        break;
5205    case ALT_CLK_MPU_L2_RAM:
5206        name =  "MPU_L2_RAM";
5207        break;
5208    case ALT_CLK_MPU_PERIPH:
5209        name =  "MPU_PERIPH";
5210        break;
5211    case ALT_CLK_L3_MAIN:
5212        name =  "L3_MAIN";
5213        break;
5214    case ALT_CLK_L3_MP:
5215        name =  "L3_MP";
5216        break;
5217    case ALT_CLK_L3_SP:
5218        name =  "L3_SP";
5219        break;
5220    case ALT_CLK_L4_MAIN:
5221        name =  "L4_MAIN";
5222        break;
5223    case ALT_CLK_L4_MP:
5224        name =  "L4_MP";
5225        break;
5226    case ALT_CLK_L4_SP:
5227        name =  "L4_SP";
5228        break;
5229    case ALT_CLK_DBG_BASE:
5230        name =  "DBG_BASE";
5231        break;
5232    case ALT_CLK_DBG_AT:
5233        name =  "DBG_AT";
5234        break;
5235    case ALT_CLK_DBG_TRACE:
5236        name =  "DBG_TRACE";
5237        break;
5238    case ALT_CLK_DBG_TIMER:
5239        name =  "DBG_TIMER";
5240        break;
5241    case ALT_CLK_DBG:
5242        name =  "DBG";
5243        break;
5244    case ALT_CLK_MAIN_QSPI:
5245        name =  "MAIN_QSPI";
5246        break;
5247    case ALT_CLK_MAIN_NAND_SDMMC:
5248        name =  "MAIN_NAND_SDMMC";
5249        break;
5250    case ALT_CLK_CFG:
5251        name =  "CFG";
5252        break;
5253    case ALT_CLK_H2F_USER0:
5254        name =  "H2F_USER0";
5255        break;
5256
5257        // Peripherals Clock Group - The following clocks are derived from the Peripheral PLL.
5258    case ALT_CLK_PERIPHERAL_PLL_C0:
5259        name =  "PERIPHERAL_PLL_C0";
5260        break;
5261    case ALT_CLK_PERIPHERAL_PLL_C1:
5262        name =  "PERIPHERAL_PLL_C1";
5263        break;
5264    case ALT_CLK_PERIPHERAL_PLL_C2:
5265        name =  "PERIPHERAL_PLL_C2";
5266        break;
5267    case ALT_CLK_PERIPHERAL_PLL_C3:
5268        name =  "PERIPHERAL_PLL_C3";
5269        break;
5270    case ALT_CLK_PERIPHERAL_PLL_C4:
5271        name =  "PERIPHERAL_PLL_C4";
5272        break;
5273    case ALT_CLK_PERIPHERAL_PLL_C5:
5274        name =  "PERIPHERAL_PLL_C5";
5275        break;
5276    case ALT_CLK_USB_MP:
5277        name =  "USB_MP";
5278        break;
5279    case ALT_CLK_SPI_M:
5280        name =  "SPI_M";
5281        break;
5282    case ALT_CLK_QSPI:
5283        name =  "QSPI";
5284        break;
5285    case ALT_CLK_NAND_X:
5286        name =  "NAND_X";
5287        break;
5288    case ALT_CLK_NAND:
5289        name =  "NAND";
5290        break;
5291    case ALT_CLK_SDMMC:
5292        name =  "SDMMC";
5293        break;
5294    case ALT_CLK_EMAC0:
5295        name =  "EMAC0";
5296        break;
5297    case ALT_CLK_EMAC1:
5298        name =  "EMAC1";
5299        break;
5300    case ALT_CLK_CAN0:
5301        name =  "CAN0";
5302        break;
5303    case ALT_CLK_CAN1:
5304        name =  "CAN1";
5305        break;
5306    case ALT_CLK_GPIO_DB:
5307        name =  "GPIO_DB";
5308        break;
5309    case ALT_CLK_H2F_USER1:
5310        name =  "H2F_USER1";
5311        break;
5312
5313        // SDRAM Clock Group - The following clocks are derived from the SDRAM PLL.
5314    case ALT_CLK_SDRAM_PLL_C0:
5315        name =  "SDRAM_PLL_C0";
5316        break;
5317    case ALT_CLK_SDRAM_PLL_C1:
5318        name =  "SDRAM_PLL_C1";
5319        break;
5320    case ALT_CLK_SDRAM_PLL_C2:
5321        name =  "SDRAM_PLL_C2";
5322        break;
5323    case ALT_CLK_SDRAM_PLL_C3:
5324        name =  "SDRAM_PLL_C3";
5325        break;
5326    case ALT_CLK_SDRAM_PLL_C4:
5327        name =  "SDRAM_PLL_C4";
5328        break;
5329    case ALT_CLK_SDRAM_PLL_C5:
5330        name =  "SDRAM_PLL_C5";
5331        break;
5332    case ALT_CLK_DDR_DQS:
5333        name =  "DDR_DQS";
5334        break;
5335    case ALT_CLK_DDR_2X_DQS:
5336        name =  "DDR_2X_DQS";
5337        break;
5338    case ALT_CLK_DDR_DQ:
5339        name =  "DDR_DQ";
5340        break;
5341    case ALT_CLK_H2F_USER2:
5342        name =  "H2F_USER2";
5343        break;
5344
5345        // Clock Output Pins
5346    case ALT_CLK_OUT_PIN_EMAC0_TX:
5347        name =  "OUT_PIN_EMAC0_TX";
5348        break;
5349    case ALT_CLK_OUT_PIN_EMAC1_TX:
5350        name =  "OUT_PIN_EMAC1_TX";
5351        break;
5352    case ALT_CLK_OUT_PIN_SDMMC:
5353        name =  "OUT_PIN_SDMMC";
5354        break;
5355    case ALT_CLK_OUT_PIN_I2C0_SCL:
5356        name =  "OUT_PIN_I2C0_SCL";
5357        break;
5358    case ALT_CLK_OUT_PIN_I2C1_SCL:
5359        name =  "OUT_PIN_I2C1_SCL";
5360        break;
5361    case ALT_CLK_OUT_PIN_I2C2_SCL:
5362        name =  "OUT_PIN_I2C2_SCL";
5363        break;
5364    case ALT_CLK_OUT_PIN_I2C3_SCL:
5365        name =  "OUT_PIN_I2C3_SCL";
5366        break;
5367    case ALT_CLK_OUT_PIN_SPIM0:
5368        name =  "OUT_PIN_SPIM0";
5369        break;
5370    case ALT_CLK_OUT_PIN_SPIM1:
5371        name =  "OUT_PIN_SPIM1";
5372        break;
5373    case ALT_CLK_OUT_PIN_QSPI:
5374        name =  "OUT_PIN_QSPI";
5375        break;
5376    case ALT_CLK_UNKNOWN:
5377        name =  "UNKNOWN";
5378        break;
5379
5380        // do *not* put a 'default' statement here. Then the compiler will throw
5381        // an error if another clock id enum is added if the corresponding
5382        // string is not added to this function.
5383    }
5384
5385    if (name != NULL)
5386    {
5387        snprintf(output, size, "ALT_CLK_%s", name);
5388        return ALT_E_SUCCESS;
5389    }
5390    else
5391    {
5392        return ALT_E_BAD_ARG;
5393    }
5394}
5395
5396
5397//
5398// alt_clk_pll_cntr_maxfreq_recalc() recalculate the maxmum frequency of the specified clock.
5399//
5400ALT_STATUS_CODE alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_t clk, ALT_PLL_CNTR_FREQMAX_t * maxfreq)
5401{
5402    ALT_STATUS_CODE ret = ALT_E_BAD_ARG;
5403        alt_freq_t freq;
5404
5405        ret = alt_clk_freq_get(clk, &freq);
5406
5407        if (ret == ALT_E_SUCCESS)
5408    {
5409
5410        switch (clk)
5411        {
5412            // Main Clock Group
5413        case ALT_CLK_MAIN_PLL_C0:
5414            maxfreq->MainPLL_C0 = freq;
5415                        printf("alt_pll_cntr_maxfreq.MainPLL_C0   = %10d\n", (unsigned int)freq);
5416            break;
5417        case ALT_CLK_MAIN_PLL_C1:
5418            maxfreq->MainPLL_C1 = freq;
5419                        printf("alt_pll_cntr_maxfreq.MainPLL_C1   = %10d\n", (unsigned int)freq);
5420            break;
5421        case ALT_CLK_MAIN_PLL_C2:
5422            maxfreq->MainPLL_C2 = freq;
5423                        printf("alt_pll_cntr_maxfreq.MainPLL_C2   = %10d\n", (unsigned int)freq);
5424            break;
5425        case ALT_CLK_MAIN_PLL_C3:
5426            maxfreq->MainPLL_C3 = freq;
5427                        printf("alt_pll_cntr_maxfreq.MainPLL_C3   = %10d\n", (unsigned int)freq);
5428            break;
5429        case ALT_CLK_MAIN_PLL_C4:
5430            maxfreq->MainPLL_C4 = freq;
5431                        printf("alt_pll_cntr_maxfreq.MainPLL_C4   = %10d\n", (unsigned int)freq);
5432            break;
5433        case ALT_CLK_MAIN_PLL_C5:
5434            maxfreq->MainPLL_C5 = freq;
5435                        printf("alt_pll_cntr_maxfreq.MainPLL_C5   = %10d\n", (unsigned int)freq);
5436            break;
5437
5438            // Peripheral Clock Group
5439        case ALT_CLK_PERIPHERAL_PLL_C0:
5440            maxfreq->PeriphPLL_C0 = freq;
5441                        printf("alt_pll_cntr_maxfreq.PeriphPLL_C0 = %10d\n", (unsigned int)freq);
5442            break;
5443        case ALT_CLK_PERIPHERAL_PLL_C1:
5444            maxfreq->PeriphPLL_C1 = freq;
5445                        printf("alt_pll_cntr_maxfreq.PeriphPLL_C1 = %10d\n", (unsigned int)freq);
5446            break;
5447        case ALT_CLK_PERIPHERAL_PLL_C2:
5448            maxfreq->PeriphPLL_C2 = freq;
5449                        printf("alt_pll_cntr_maxfreq.PeriphPLL_C2 = %10d\n", (unsigned int)freq);
5450            break;
5451        case ALT_CLK_PERIPHERAL_PLL_C3:
5452            maxfreq->PeriphPLL_C3 = freq;
5453                        printf("alt_pll_cntr_maxfreq.PeriphPLL_C3 = %10d\n", (unsigned int)freq);
5454            break;
5455        case ALT_CLK_PERIPHERAL_PLL_C4:
5456            maxfreq->PeriphPLL_C4 = freq;
5457                        printf("alt_pll_cntr_maxfreq.PeriphPLL_C4 = %10d\n", (unsigned int)freq);
5458            break;
5459        case ALT_CLK_PERIPHERAL_PLL_C5:
5460            maxfreq->PeriphPLL_C5 = freq;
5461                        printf("alt_pll_cntr_maxfreq.PeriphPLL_C5 = %10d\n", (unsigned int)freq);
5462            break;
5463
5464            // SDRAM Clock Group
5465        case ALT_CLK_SDRAM_PLL_C0:
5466            maxfreq->SDRAMPLL_C0 = freq;
5467                        printf("alt_pll_cntr_maxfreq.SDRAMPLL_C0  = %10d\n", (unsigned int)freq);
5468            break;
5469        case ALT_CLK_SDRAM_PLL_C1:
5470            maxfreq->SDRAMPLL_C1 = freq;
5471                        printf("alt_pll_cntr_maxfreq.SDRAMPLL_C1  = %10d\n", (unsigned int)freq);
5472            break;
5473        case ALT_CLK_SDRAM_PLL_C2:
5474            maxfreq->SDRAMPLL_C2 = freq;
5475                        printf("alt_pll_cntr_maxfreq.SDRAMPLL_C2  = %10d\n", (unsigned int)freq);
5476            break;
5477        case ALT_CLK_SDRAM_PLL_C5:
5478            maxfreq->SDRAMPLL_C5 = freq;
5479                        printf("alt_pll_cntr_maxfreq.SDRAMPLL_C5  = %10d\n", (unsigned int)freq);
5480            break;
5481        default:
5482            ret = ALT_E_BAD_ARG;
5483                        printf("bad max frequency parameter\n");
5484            break;
5485        }   // end of switch-case construct
5486    }
5487
5488    return ret;
5489}
5490
5491//
5492//  u-boot preloader actually initialize clock manager circuitry
5493//
5494//  alt_clk_clkmgr_init() attempt to fix the pll counter max frequencies, since
5495//  thses frequencies are not known in advance until u-boot programmed clock manager.
5496//
5497ALT_STATUS_CODE alt_clk_clkmgr_init(void)
5498{
5499    ALT_STATUS_CODE ret = ALT_E_SUCCESS;
5500    ALT_STATUS_CODE status ;
5501
5502        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C0,&alt_pll_cntr_maxfreq );
5503        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5504
5505        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C1,&alt_pll_cntr_maxfreq );
5506        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5507
5508        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C2,&alt_pll_cntr_maxfreq );
5509        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5510
5511        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C3,&alt_pll_cntr_maxfreq );
5512        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5513
5514        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C4,&alt_pll_cntr_maxfreq );
5515        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5516
5517        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_MAIN_PLL_C5,&alt_pll_cntr_maxfreq );
5518        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5519
5520        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C0,&alt_pll_cntr_maxfreq );
5521        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5522
5523        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C1,&alt_pll_cntr_maxfreq );
5524        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5525
5526        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C2,&alt_pll_cntr_maxfreq );
5527        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5528
5529        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C3,&alt_pll_cntr_maxfreq );
5530        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5531
5532        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C4,&alt_pll_cntr_maxfreq );
5533        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5534
5535        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_PERIPHERAL_PLL_C5,&alt_pll_cntr_maxfreq );
5536        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5537
5538
5539        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C0,&alt_pll_cntr_maxfreq );
5540        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5541
5542        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C1,&alt_pll_cntr_maxfreq );
5543        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5544
5545        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C2,&alt_pll_cntr_maxfreq );
5546        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5547
5548        status = alt_clk_pll_cntr_maxfreq_recalc(ALT_CLK_SDRAM_PLL_C5,&alt_pll_cntr_maxfreq );
5549        if (status != ALT_E_SUCCESS) ret = ALT_E_ERROR;
5550
5551
5552        return ret;
5553}
5554
Note: See TracBrowser for help on using the repository browser.