hc
2023-11-22 f743a7adbd6e230d66a6206fa115b59fec2d88eb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 *
 * Copyright (C) 2004-2007, 2012 Freescale Semiconductor, Inc.
 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */
 
#include <common.h>
#include <asm/processor.h>
 
#include <asm/immap.h>
#include <asm/io.h>
 
DECLARE_GLOBAL_DATA_PTR;
 
/*
 * Low Power Divider specifications
 */
#define CLOCK_LPD_MIN        (1 << 0)    /* Divider (decoded) */
#define CLOCK_LPD_MAX        (1 << 15)    /* Divider (decoded) */
 
#define CLOCK_PLL_FVCO_MAX    540000000
#define CLOCK_PLL_FVCO_MIN    300000000
 
#define CLOCK_PLL_FSYS_MAX    266666666
#define CLOCK_PLL_FSYS_MIN    100000000
#define MHZ            1000000
 
void clock_enter_limp(int lpdiv)
{
   ccm_t *ccm = (ccm_t *)MMAP_CCM;
   int i, j;
 
   /* Check bounds of divider */
   if (lpdiv < CLOCK_LPD_MIN)
       lpdiv = CLOCK_LPD_MIN;
   if (lpdiv > CLOCK_LPD_MAX)
       lpdiv = CLOCK_LPD_MAX;
 
   /* Round divider down to nearest power of two */
   for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ;
 
   /* Apply the divider to the system clock */
   clrsetbits_be16(&ccm->cdr, 0x0f00, CCM_CDR_LPDIV(i));
 
   /* Enable Limp Mode */
   setbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
}
 
/*
 * brief   Exit Limp mode
 * warning The PLL should be set and locked prior to exiting Limp mode
 */
void clock_exit_limp(void)
{
   ccm_t *ccm = (ccm_t *)MMAP_CCM;
   pll_t *pll = (pll_t *)MMAP_PLL;
 
   /* Exit Limp mode */
   clrbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
 
   /* Wait for the PLL to lock */
   while (!(in_be32(&pll->psr) & PLL_PSR_LOCK))
       ;
}
 
/*
 * get_clocks() fills in gd->cpu_clock and gd->bus_clk
 */
int get_clocks(void)
{
 
   ccm_t *ccm = (ccm_t *)MMAP_CCM;
   pll_t *pll = (pll_t *)MMAP_PLL;
   int vco, temp, pcrvalue, pfdr;
   u8 bootmode;
 
   pcrvalue = in_be32(&pll->pcr) & 0xFF0F0FFF;
   pfdr = pcrvalue >> 24;
 
   if (pfdr == 0x1E)
       bootmode = 0;    /* Normal Mode */
 
#ifdef CONFIG_CF_SBF
   bootmode = 3;        /* Serial Mode */
#endif
 
   if (bootmode == 0) {
       /* Normal mode */
       vco = ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC;
       if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {
           /* Default value */
           pcrvalue = (in_be32(&pll->pcr) & 0x00FFFFFF);
           pcrvalue |= 0x1E << 24;
           out_be32(&pll->pcr, pcrvalue);
           vco =
               ((in_be32(&pll->pcr) & 0xFF000000) >> 24) *
               CONFIG_SYS_INPUT_CLKSRC;
       }
       gd->arch.vco_clk = vco;    /* Vco clock */
   } else if (bootmode == 3) {
       /* serial mode */
       vco = ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC;
       gd->arch.vco_clk = vco;    /* Vco clock */
   }
 
   if ((in_be16(&ccm->ccr) & CCM_MISCCR_LIMP) == CCM_MISCCR_LIMP) {
       /* Limp mode */
   } else {
       gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC; /* Input clock */
 
       temp = (in_be32(&pll->pcr) & PLL_PCR_OUTDIV1_MASK) + 1;
       gd->cpu_clk = vco / temp;    /* cpu clock */
 
       temp = ((in_be32(&pll->pcr) & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;
       gd->arch.flb_clk = vco / temp;    /* flexbus clock */
       gd->bus_clk = gd->arch.flb_clk;
   }
 
#ifdef CONFIG_SYS_I2C_FSL
   gd->arch.i2c1_clk = gd->bus_clk;
#endif
 
   return (0);
}