]>
Commit | Line | Data |
---|---|---|
552ff8f1 JR |
1 | /* |
2 | * (C) Copyright 2009 DENX Software Engineering | |
3 | * Author: John Rigby <jrigby@gmail.com> | |
4 | * | |
5 | * Based on mx27/generic.c: | |
6 | * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> | |
7 | * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> | |
8 | * | |
1a459660 | 9 | * SPDX-License-Identifier: GPL-2.0+ |
552ff8f1 JR |
10 | */ |
11 | ||
12 | #include <common.h> | |
13 | #include <div64.h> | |
14 | #include <netdev.h> | |
15 | #include <asm/io.h> | |
fc5ad477 | 16 | #include <asm/arch-imx/cpu.h> |
552ff8f1 | 17 | #include <asm/arch/imx-regs.h> |
42d25327 | 18 | #include <asm/arch/clock.h> |
552ff8f1 | 19 | |
42d25327 | 20 | #ifdef CONFIG_FSL_ESDHC |
6be58005 BT |
21 | #include <fsl_esdhc.h> |
22 | ||
42d25327 TK |
23 | DECLARE_GLOBAL_DATA_PTR; |
24 | #endif | |
25 | ||
552ff8f1 JR |
26 | /* |
27 | * get the system pll clock in Hz | |
28 | * | |
29 | * mfi + mfn / (mfd +1) | |
30 | * f = 2 * f_ref * -------------------- | |
31 | * pd + 1 | |
32 | */ | |
77f11a99 | 33 | static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) |
552ff8f1 JR |
34 | { |
35 | unsigned int mfi = (pll >> CCM_PLL_MFI_SHIFT) | |
36 | & CCM_PLL_MFI_MASK; | |
3c76add2 | 37 | int mfn = (pll >> CCM_PLL_MFN_SHIFT) |
552ff8f1 JR |
38 | & CCM_PLL_MFN_MASK; |
39 | unsigned int mfd = (pll >> CCM_PLL_MFD_SHIFT) | |
40 | & CCM_PLL_MFD_MASK; | |
41 | unsigned int pd = (pll >> CCM_PLL_PD_SHIFT) | |
42 | & CCM_PLL_PD_MASK; | |
43 | ||
44 | mfi = mfi <= 5 ? 5 : mfi; | |
3c76add2 BT |
45 | mfn = mfn >= 512 ? mfn - 1024 : mfn; |
46 | mfd += 1; | |
47 | pd += 1; | |
552ff8f1 | 48 | |
3c76add2 BT |
49 | return lldiv(2 * (u64) f_ref * (mfi * mfd + mfn), |
50 | mfd * pd); | |
552ff8f1 JR |
51 | } |
52 | ||
77f11a99 | 53 | static ulong imx_get_mpllclk(void) |
552ff8f1 JR |
54 | { |
55 | struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; | |
1b2080f3 | 56 | ulong fref = MXC_HCLK; |
552ff8f1 | 57 | |
77f11a99 | 58 | return imx_decode_pll(readl(&ccm->mpctl), fref); |
552ff8f1 JR |
59 | } |
60 | ||
9baefa46 | 61 | static ulong imx_get_armclk(void) |
552ff8f1 JR |
62 | { |
63 | struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; | |
77f11a99 FE |
64 | ulong cctl = readl(&ccm->cctl); |
65 | ulong fref = imx_get_mpllclk(); | |
552ff8f1 JR |
66 | ulong div; |
67 | ||
68 | if (cctl & CCM_CCTL_ARM_SRC) | |
fac7c817 | 69 | fref = lldiv((u64) fref * 3, 4); |
552ff8f1 JR |
70 | |
71 | div = ((cctl >> CCM_CCTL_ARM_DIV_SHIFT) | |
72 | & CCM_CCTL_ARM_DIV_MASK) + 1; | |
73 | ||
fac7c817 | 74 | return fref / div; |
552ff8f1 JR |
75 | } |
76 | ||
9baefa46 | 77 | static ulong imx_get_ahbclk(void) |
552ff8f1 JR |
78 | { |
79 | struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; | |
77f11a99 FE |
80 | ulong cctl = readl(&ccm->cctl); |
81 | ulong fref = imx_get_armclk(); | |
552ff8f1 JR |
82 | ulong div; |
83 | ||
84 | div = ((cctl >> CCM_CCTL_AHB_DIV_SHIFT) | |
85 | & CCM_CCTL_AHB_DIV_MASK) + 1; | |
86 | ||
fac7c817 | 87 | return fref / div; |
552ff8f1 JR |
88 | } |
89 | ||
c3b51890 BT |
90 | static ulong imx_get_ipgclk(void) |
91 | { | |
92 | return imx_get_ahbclk() / 2; | |
93 | } | |
94 | ||
9baefa46 | 95 | static ulong imx_get_perclk(int clk) |
552ff8f1 JR |
96 | { |
97 | struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; | |
77f11a99 | 98 | ulong fref = imx_get_ahbclk(); |
552ff8f1 JR |
99 | ulong div; |
100 | ||
77f11a99 FE |
101 | div = readl(&ccm->pcdr[CCM_PERCLK_REG(clk)]); |
102 | div = ((div >> CCM_PERCLK_SHIFT(clk)) & CCM_PERCLK_MASK) + 1; | |
552ff8f1 | 103 | |
fac7c817 | 104 | return fref / div; |
552ff8f1 JR |
105 | } |
106 | ||
42d25327 TK |
107 | unsigned int mxc_get_clock(enum mxc_clock clk) |
108 | { | |
109 | if (clk >= MXC_CLK_NUM) | |
110 | return -1; | |
111 | switch (clk) { | |
112 | case MXC_ARM_CLK: | |
113 | return imx_get_armclk(); | |
c3b51890 BT |
114 | case MXC_AHB_CLK: |
115 | return imx_get_ahbclk(); | |
116 | case MXC_IPG_CLK: | |
117 | case MXC_CSPI_CLK: | |
42d25327 | 118 | case MXC_FEC_CLK: |
17c7cf71 | 119 | return imx_get_ipgclk(); |
42d25327 TK |
120 | default: |
121 | return imx_get_perclk(clk); | |
122 | } | |
123 | } | |
124 | ||
986d0d1b FE |
125 | u32 get_cpu_rev(void) |
126 | { | |
127 | u32 srev; | |
128 | u32 system_rev = 0x25000; | |
129 | ||
130 | /* read SREV register from IIM module */ | |
131 | struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; | |
132 | srev = readl(&iim->iim_srev); | |
133 | ||
134 | switch (srev) { | |
135 | case 0x00: | |
136 | system_rev |= CHIP_REV_1_0; | |
137 | break; | |
138 | case 0x01: | |
139 | system_rev |= CHIP_REV_1_1; | |
140 | break; | |
8a57fdc6 EB |
141 | case 0x02: |
142 | system_rev |= CHIP_REV_1_2; | |
143 | break; | |
986d0d1b FE |
144 | default: |
145 | system_rev |= 0x8000; | |
146 | break; | |
147 | } | |
148 | ||
149 | return system_rev; | |
150 | } | |
151 | ||
552ff8f1 | 152 | #if defined(CONFIG_DISPLAY_CPUINFO) |
e6ec1761 FE |
153 | static char *get_reset_cause(void) |
154 | { | |
155 | /* read RCSR register from CCM module */ | |
156 | struct ccm_regs *ccm = | |
157 | (struct ccm_regs *)IMX_CCM_BASE; | |
158 | ||
159 | u32 cause = readl(&ccm->rcsr) & 0x0f; | |
160 | ||
161 | if (cause == 0) | |
162 | return "POR"; | |
163 | else if (cause == 1) | |
164 | return "RST"; | |
165 | else if ((cause & 2) == 2) | |
166 | return "WDOG"; | |
167 | else if ((cause & 4) == 4) | |
168 | return "SW RESET"; | |
169 | else if ((cause & 8) == 8) | |
170 | return "JTAG"; | |
171 | else | |
172 | return "unknown reset"; | |
173 | ||
174 | } | |
175 | ||
77f11a99 | 176 | int print_cpuinfo(void) |
552ff8f1 JR |
177 | { |
178 | char buf[32]; | |
986d0d1b | 179 | u32 cpurev = get_cpu_rev(); |
552ff8f1 | 180 | |
957dc024 | 181 | printf("CPU: Freescale i.MX25 rev%d.%d%s at %s MHz\n", |
986d0d1b FE |
182 | (cpurev & 0xF0) >> 4, (cpurev & 0x0F), |
183 | ((cpurev & 0x8000) ? " unknown" : ""), | |
77f11a99 | 184 | strmhz(buf, imx_get_armclk())); |
8ed5e4ce | 185 | printf("Reset cause: %s\n", get_reset_cause()); |
552ff8f1 JR |
186 | return 0; |
187 | } | |
188 | #endif | |
189 | ||
e107c7e9 BT |
190 | void enable_caches(void) |
191 | { | |
192 | #ifndef CONFIG_SYS_DCACHE_OFF | |
193 | /* Enable D-cache. I-cache is already enabled in start.S */ | |
194 | dcache_enable(); | |
195 | #endif | |
196 | } | |
197 | ||
f7542638 BT |
198 | #if defined(CONFIG_FEC_MXC) |
199 | /* | |
200 | * Initializes on-chip ethernet controllers. | |
201 | * to override, implement board_eth_init() | |
202 | */ | |
77f11a99 | 203 | int cpu_eth_init(bd_t *bis) |
552ff8f1 | 204 | { |
552ff8f1 JR |
205 | struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; |
206 | ulong val; | |
207 | ||
77f11a99 | 208 | val = readl(&ccm->cgr0); |
552ff8f1 | 209 | val |= (1 << 23); |
77f11a99 FE |
210 | writel(val, &ccm->cgr0); |
211 | return fecmxc_initialize(bis); | |
552ff8f1 | 212 | } |
f7542638 | 213 | #endif |
552ff8f1 | 214 | |
42d25327 TK |
215 | int get_clocks(void) |
216 | { | |
217 | #ifdef CONFIG_FSL_ESDHC | |
6be58005 | 218 | #if CONFIG_SYS_FSL_ESDHC_ADDR == IMX_MMC_SDHC2_BASE |
e9adeca3 | 219 | gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); |
6be58005 | 220 | #else |
e9adeca3 | 221 | gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); |
6be58005 | 222 | #endif |
42d25327 TK |
223 | #endif |
224 | return 0; | |
225 | } | |
226 | ||
6be58005 | 227 | #ifdef CONFIG_FSL_ESDHC |
552ff8f1 JR |
228 | /* |
229 | * Initializes on-chip MMC controllers. | |
230 | * to override, implement board_mmc_init() | |
231 | */ | |
77f11a99 | 232 | int cpu_mmc_init(bd_t *bis) |
552ff8f1 | 233 | { |
6be58005 | 234 | return fsl_esdhc_mmc_init(bis); |
552ff8f1 | 235 | } |
6be58005 | 236 | #endif |
552ff8f1 | 237 | |
552ff8f1 | 238 | #ifdef CONFIG_FEC_MXC |
be252b65 | 239 | void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) |
565e39c5 LHR |
240 | { |
241 | int i; | |
242 | struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; | |
243 | struct fuse_bank *bank = &iim->bank[0]; | |
244 | struct fuse_bank0_regs *fuse = | |
245 | (struct fuse_bank0_regs *)bank->fuse_regs; | |
246 | ||
247 | for (i = 0; i < 6; i++) | |
248 | mac[i] = readl(&fuse->mac_addr[i]) & 0xff; | |
249 | } | |
552ff8f1 | 250 | #endif /* CONFIG_FEC_MXC */ |