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