blob: 41cb9e999adc65e3fb0b52e59ee77705547f6b14 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -05002/*
3 *
Alison Wang8d8dac92012-03-26 21:49:08 +00004 * Copyright (C) 2004-2007, 2012 Freescale Semiconductor, Inc.
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -05005 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -05006 */
7
Simon Glass85d65312019-12-28 10:44:58 -07008#include <clock_legacy.h>
Simon Glass3ba929a2020-10-30 21:38:53 -06009#include <asm/global_data.h>
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050010#include <asm/processor.h>
11
12#include <asm/immap.h>
Alison Wang8d8dac92012-03-26 21:49:08 +000013#include <asm/io.h>
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050014
15DECLARE_GLOBAL_DATA_PTR;
16
17/*
18 * Low Power Divider specifications
19 */
20#define CLOCK_LPD_MIN (1 << 0) /* Divider (decoded) */
21#define CLOCK_LPD_MAX (1 << 15) /* Divider (decoded) */
22
23#define CLOCK_PLL_FVCO_MAX 540000000
24#define CLOCK_PLL_FVCO_MIN 300000000
25
26#define CLOCK_PLL_FSYS_MAX 266666666
27#define CLOCK_PLL_FSYS_MIN 100000000
28#define MHZ 1000000
29
30void clock_enter_limp(int lpdiv)
31{
Alison Wang8d8dac92012-03-26 21:49:08 +000032 ccm_t *ccm = (ccm_t *)MMAP_CCM;
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050033 int i, j;
34
35 /* Check bounds of divider */
36 if (lpdiv < CLOCK_LPD_MIN)
37 lpdiv = CLOCK_LPD_MIN;
38 if (lpdiv > CLOCK_LPD_MAX)
39 lpdiv = CLOCK_LPD_MAX;
40
41 /* Round divider down to nearest power of two */
42 for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ;
43
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050044 /* Enable Limp Mode */
Alison Wang8d8dac92012-03-26 21:49:08 +000045 setbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050046}
47
48/*
49 * brief Exit Limp mode
50 * warning The PLL should be set and locked prior to exiting Limp mode
51 */
52void clock_exit_limp(void)
53{
Alison Wang8d8dac92012-03-26 21:49:08 +000054 ccm_t *ccm = (ccm_t *)MMAP_CCM;
55 pll_t *pll = (pll_t *)MMAP_PLL;
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050056
57 /* Exit Limp mode */
Alison Wang8d8dac92012-03-26 21:49:08 +000058 clrbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050059
60 /* Wait for the PLL to lock */
Alison Wang8d8dac92012-03-26 21:49:08 +000061 while (!(in_be32(&pll->psr) & PLL_PSR_LOCK))
62 ;
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050063}
64
Alison Wangfdc2fb12012-10-18 19:25:51 +000065#ifdef CONFIG_MCF5441x
66void setup_5441x_clocks(void)
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -050067{
Alison Wangfdc2fb12012-10-18 19:25:51 +000068 ccm_t *ccm = (ccm_t *)MMAP_CCM;
69 pll_t *pll = (pll_t *)MMAP_PLL;
70 int temp, vco = 0, bootmod_ccr, pdr;
71
72 bootmod_ccr = (in_be16(&ccm->ccr) & CCM_CCR_BOOTMOD) >> 14;
73
74 switch (bootmod_ccr) {
75 case 0:
76 out_be32(&pll->pcr, 0x00000013);
77 out_be32(&pll->pdr, 0x00e70c61);
78 clock_exit_limp();
79 break;
80 case 2:
81 break;
82 case 3:
83 break;
84 }
85
86 /*Change frequency for Modelo SER1 USB host*/
87#ifdef CONFIG_LOW_MCFCLK
88 temp = in_be32(&pll->pcr);
89 temp &= ~0x3f;
90 temp |= 5;
91 out_be32(&pll->pcr, temp);
92
93 temp = in_be32(&pll->pdr);
94 temp &= ~0x001f0000;
95 temp |= 0x00040000;
96 out_be32(&pll->pdr, temp);
97 __asm__("tpf");
98#endif
99
100 setbits_be16(&ccm->misccr2, 0x02);
101
102 vco = ((in_be32(&pll->pcr) & PLL_CR_FBKDIV_BITS) + 1) *
103 CONFIG_SYS_INPUT_CLKSRC;
Jason Jin2ecfc782013-06-26 10:21:31 +0800104 gd->arch.vco_clk = vco;
Alison Wangfdc2fb12012-10-18 19:25:51 +0000105
Jason Jin2ecfc782013-06-26 10:21:31 +0800106 gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC; /* Input clock */
TsiChung Liew23cf8fd2008-07-23 20:38:53 -0500107
Alison Wangfdc2fb12012-10-18 19:25:51 +0000108 pdr = in_be32(&pll->pdr);
109 temp = (pdr & PLL_DR_OUTDIV1_BITS) + 1;
110 gd->cpu_clk = vco / temp; /* cpu clock */
Jason Jin2ecfc782013-06-26 10:21:31 +0800111 gd->arch.flb_clk = vco / temp; /* FlexBus clock */
112 gd->arch.flb_clk >>= 1;
Vasili Galka24f413b2014-06-30 12:59:06 +0300113 if (in_be16(&ccm->misccr2) & 2) /* fsys/4 */
Jason Jin2ecfc782013-06-26 10:21:31 +0800114 gd->arch.flb_clk >>= 1;
Alison Wangfdc2fb12012-10-18 19:25:51 +0000115
116 temp = ((pdr & PLL_DR_OUTDIV2_BITS) >> 5) + 1;
117 gd->bus_clk = vco / temp; /* bus clock */
118
Angelo Dureghello95a69982018-01-25 22:42:52 +0100119 temp = ((pdr & PLL_DR_OUTDIV3_BITS) >> 10) + 1;
120 gd->arch.sdhc_clk = vco / temp;
Alison Wangfdc2fb12012-10-18 19:25:51 +0000121}
122#endif
123
Alison Wangfdc2fb12012-10-18 19:25:51 +0000124/* get_clocks() fills in gd->cpu_clock and gd->bus_clk */
125int get_clocks(void)
126{
127#ifdef CONFIG_MCF5441x
128 setup_5441x_clocks();
129#endif
Alison Wangfdc2fb12012-10-18 19:25:51 +0000130
Angelo Dureghello706bd722023-04-05 00:59:25 +0200131 if (IS_ENABLED(CONFIG_SYS_I2C_FSL))
132 gd->arch.i2c1_clk = gd->bus_clk;
TsiChung Liew0c1e3252008-08-19 03:01:19 +0600133
TsiChungLiewfc3ca3b62007-08-16 15:05:11 -0500134 return (0);
135}