Prepare v2023.10
[platform/kernel/u-boot.git] / arch / m68k / cpu / mcf5445x / speed.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *
4  * Copyright (C) 2004-2007, 2012 Freescale Semiconductor, Inc.
5  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
6  */
7
8 #include <common.h>
9 #include <clock_legacy.h>
10 #include <asm/global_data.h>
11 #include <asm/processor.h>
12
13 #include <asm/immap.h>
14 #include <asm/io.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 /*
19  * Low Power Divider specifications
20  */
21 #define CLOCK_LPD_MIN           (1 << 0)        /* Divider (decoded) */
22 #define CLOCK_LPD_MAX           (1 << 15)       /* Divider (decoded) */
23
24 #define CLOCK_PLL_FVCO_MAX      540000000
25 #define CLOCK_PLL_FVCO_MIN      300000000
26
27 #define CLOCK_PLL_FSYS_MAX      266666666
28 #define CLOCK_PLL_FSYS_MIN      100000000
29 #define MHZ                     1000000
30
31 void clock_enter_limp(int lpdiv)
32 {
33         ccm_t *ccm = (ccm_t *)MMAP_CCM;
34         int i, j;
35
36         /* Check bounds of divider */
37         if (lpdiv < CLOCK_LPD_MIN)
38                 lpdiv = CLOCK_LPD_MIN;
39         if (lpdiv > CLOCK_LPD_MAX)
40                 lpdiv = CLOCK_LPD_MAX;
41
42         /* Round divider down to nearest power of two */
43         for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ;
44
45         /* Enable Limp Mode */
46         setbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
47 }
48
49 /*
50  * brief   Exit Limp mode
51  * warning The PLL should be set and locked prior to exiting Limp mode
52  */
53 void clock_exit_limp(void)
54 {
55         ccm_t *ccm = (ccm_t *)MMAP_CCM;
56         pll_t *pll = (pll_t *)MMAP_PLL;
57
58         /* Exit Limp mode */
59         clrbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
60
61         /* Wait for the PLL to lock */
62         while (!(in_be32(&pll->psr) & PLL_PSR_LOCK))
63                 ;
64 }
65
66 #ifdef CONFIG_MCF5441x
67 void setup_5441x_clocks(void)
68 {
69         ccm_t *ccm = (ccm_t *)MMAP_CCM;
70         pll_t *pll = (pll_t *)MMAP_PLL;
71         int temp, vco = 0, bootmod_ccr, pdr;
72
73         bootmod_ccr = (in_be16(&ccm->ccr) & CCM_CCR_BOOTMOD) >> 14;
74
75         switch (bootmod_ccr) {
76         case 0:
77                 out_be32(&pll->pcr, 0x00000013);
78                 out_be32(&pll->pdr, 0x00e70c61);
79                 clock_exit_limp();
80                 break;
81         case 2:
82                 break;
83         case 3:
84                 break;
85         }
86
87         /*Change frequency for Modelo SER1 USB host*/
88 #ifdef CONFIG_LOW_MCFCLK
89         temp = in_be32(&pll->pcr);
90         temp &= ~0x3f;
91         temp |= 5;
92         out_be32(&pll->pcr, temp);
93
94         temp = in_be32(&pll->pdr);
95         temp &= ~0x001f0000;
96         temp |= 0x00040000;
97         out_be32(&pll->pdr, temp);
98         __asm__("tpf");
99 #endif
100
101         setbits_be16(&ccm->misccr2, 0x02);
102
103         vco =  ((in_be32(&pll->pcr) & PLL_CR_FBKDIV_BITS) + 1) *
104                 CONFIG_SYS_INPUT_CLKSRC;
105         gd->arch.vco_clk = vco;
106
107         gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC;     /* Input clock */
108
109         pdr = in_be32(&pll->pdr);
110         temp = (pdr & PLL_DR_OUTDIV1_BITS) + 1;
111         gd->cpu_clk = vco / temp;       /* cpu clock */
112         gd->arch.flb_clk = vco / temp;  /* FlexBus clock */
113         gd->arch.flb_clk >>= 1;
114         if (in_be16(&ccm->misccr2) & 2)         /* fsys/4 */
115                 gd->arch.flb_clk >>= 1;
116
117         temp = ((pdr & PLL_DR_OUTDIV2_BITS) >> 5) + 1;
118         gd->bus_clk = vco / temp;       /* bus clock */
119
120         temp = ((pdr & PLL_DR_OUTDIV3_BITS) >> 10) + 1;
121         gd->arch.sdhc_clk = vco / temp;
122 }
123 #endif
124
125 /* get_clocks() fills in gd->cpu_clock and gd->bus_clk */
126 int get_clocks(void)
127 {
128 #ifdef CONFIG_MCF5441x
129         setup_5441x_clocks();
130 #endif
131
132         if (IS_ENABLED(CONFIG_SYS_I2C_FSL))
133                 gd->arch.i2c1_clk = gd->bus_clk;
134
135         return (0);
136 }