]>
Commit | Line | Data |
---|---|---|
f852ce72 KG |
1 | /* |
2 | * Copyright 2007 Freescale Semiconductor, Inc. | |
3 | * | |
4 | * (C) Copyright 2000 | |
5 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
6 | * | |
7 | * See file CREDITS for list of people who contributed to this | |
8 | * project. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public License as | |
12 | * published by the Free Software Foundation; either version 2 of | |
13 | * the License, or (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program; if not, write to the Free Software | |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
23 | * MA 02111-1307 USA | |
24 | */ | |
25 | ||
26 | #include <common.h> | |
27 | #include <libfdt.h> | |
28 | #include <fdt_support.h> | |
730b2fcf | 29 | #include <asm/processor.h> |
f852ce72 | 30 | |
69018ce2 | 31 | extern void ft_qe_setup(void *blob); |
6b70ffb9 | 32 | |
ec2b74ff KG |
33 | #ifdef CONFIG_MP |
34 | #include "mp.h" | |
35 | DECLARE_GLOBAL_DATA_PTR; | |
36 | ||
37 | void ft_fixup_cpu(void *blob, u64 memory_limit) | |
38 | { | |
39 | int off; | |
40 | ulong spin_tbl_addr = get_spin_addr(); | |
41 | u32 bootpg, id = get_my_id(); | |
42 | ||
43 | /* if we have 4G or more of memory, put the boot page at 4Gb-4k */ | |
44 | if ((u64)gd->ram_size > 0xfffff000) | |
45 | bootpg = 0xfffff000; | |
46 | else | |
47 | bootpg = gd->ram_size - 4096; | |
48 | ||
49 | off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); | |
50 | while (off != -FDT_ERR_NOTFOUND) { | |
51 | u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); | |
52 | ||
53 | if (reg) { | |
54 | if (*reg == id) { | |
55 | fdt_setprop_string(blob, off, "status", "okay"); | |
56 | } else { | |
0878af16 | 57 | u64 val = *reg * SIZE_BOOT_ENTRY + spin_tbl_addr; |
ec2b74ff KG |
58 | val = cpu_to_fdt32(val); |
59 | fdt_setprop_string(blob, off, "status", | |
60 | "disabled"); | |
61 | fdt_setprop_string(blob, off, "enable-method", | |
62 | "spin-table"); | |
63 | fdt_setprop(blob, off, "cpu-release-addr", | |
64 | &val, sizeof(val)); | |
65 | } | |
66 | } else { | |
67 | printf ("cpu NULL\n"); | |
68 | } | |
69 | off = fdt_node_offset_by_prop_value(blob, off, | |
70 | "device_type", "cpu", 4); | |
71 | } | |
72 | ||
73 | /* Reserve the boot page so OSes dont use it */ | |
74 | if ((u64)bootpg < memory_limit) { | |
75 | off = fdt_add_mem_rsv(blob, bootpg, (u64)4096); | |
76 | if (off < 0) | |
77 | printf("%s: %s\n", __FUNCTION__, fdt_strerror(off)); | |
78 | } | |
79 | } | |
80 | #endif | |
69018ce2 | 81 | |
730b2fcf KG |
82 | #ifdef CONFIG_L2_CACHE |
83 | /* return size in kilobytes */ | |
84 | static inline u32 l2cache_size(void) | |
85 | { | |
6d0f6bcf | 86 | volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR; |
730b2fcf KG |
87 | volatile u32 l2siz_field = (l2cache->l2ctl >> 28) & 0x3; |
88 | u32 ver = SVR_SOC_VER(get_svr()); | |
89 | ||
90 | switch (l2siz_field) { | |
91 | case 0x0: | |
92 | break; | |
93 | case 0x1: | |
94 | if (ver == SVR_8540 || ver == SVR_8560 || | |
95 | ver == SVR_8541 || ver == SVR_8541_E || | |
96 | ver == SVR_8555 || ver == SVR_8555_E) | |
97 | return 128; | |
98 | else | |
99 | return 256; | |
100 | break; | |
101 | case 0x2: | |
102 | if (ver == SVR_8540 || ver == SVR_8560 || | |
103 | ver == SVR_8541 || ver == SVR_8541_E || | |
104 | ver == SVR_8555 || ver == SVR_8555_E) | |
105 | return 256; | |
106 | else | |
107 | return 512; | |
108 | break; | |
109 | case 0x3: | |
110 | return 1024; | |
111 | break; | |
112 | } | |
113 | ||
114 | return 0; | |
115 | } | |
116 | ||
117 | static inline void ft_fixup_l2cache(void *blob) | |
118 | { | |
119 | int len, off; | |
120 | u32 *ph; | |
121 | struct cpu_type *cpu = identify_cpu(SVR_SOC_VER(get_svr())); | |
122 | char compat_buf[38]; | |
123 | ||
124 | const u32 line_size = 32; | |
125 | const u32 num_ways = 8; | |
126 | const u32 size = l2cache_size() * 1024; | |
127 | const u32 num_sets = size / (line_size * num_ways); | |
128 | ||
129 | off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); | |
130 | if (off < 0) { | |
131 | debug("no cpu node fount\n"); | |
132 | return; | |
133 | } | |
134 | ||
135 | ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0); | |
136 | ||
137 | if (ph == NULL) { | |
138 | debug("no next-level-cache property\n"); | |
139 | return ; | |
140 | } | |
141 | ||
142 | off = fdt_node_offset_by_phandle(blob, *ph); | |
143 | if (off < 0) { | |
144 | printf("%s: %s\n", __func__, fdt_strerror(off)); | |
145 | return ; | |
146 | } | |
147 | ||
148 | if (cpu) { | |
149 | len = sprintf(compat_buf, "fsl,mpc%s-l2-cache-controller", | |
150 | cpu->name); | |
151 | sprintf(&compat_buf[len + 1], "cache"); | |
152 | } | |
153 | fdt_setprop(blob, off, "cache-unified", NULL, 0); | |
154 | fdt_setprop_cell(blob, off, "cache-block-size", line_size); | |
730b2fcf KG |
155 | fdt_setprop_cell(blob, off, "cache-size", size); |
156 | fdt_setprop_cell(blob, off, "cache-sets", num_sets); | |
157 | fdt_setprop_cell(blob, off, "cache-level", 2); | |
158 | fdt_setprop(blob, off, "compatible", compat_buf, sizeof(compat_buf)); | |
159 | } | |
160 | #else | |
161 | #define ft_fixup_l2cache(x) | |
162 | #endif | |
163 | ||
164 | static inline void ft_fixup_cache(void *blob) | |
165 | { | |
166 | int off; | |
167 | ||
168 | off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); | |
169 | ||
170 | while (off != -FDT_ERR_NOTFOUND) { | |
171 | u32 l1cfg0 = mfspr(SPRN_L1CFG0); | |
172 | u32 l1cfg1 = mfspr(SPRN_L1CFG1); | |
173 | u32 isize, iline_size, inum_sets, inum_ways; | |
174 | u32 dsize, dline_size, dnum_sets, dnum_ways; | |
175 | ||
176 | /* d-side config */ | |
177 | dsize = (l1cfg0 & 0x7ff) * 1024; | |
178 | dnum_ways = ((l1cfg0 >> 11) & 0xff) + 1; | |
179 | dline_size = (((l1cfg0 >> 23) & 0x3) + 1) * 32; | |
180 | dnum_sets = dsize / (dline_size * dnum_ways); | |
181 | ||
182 | fdt_setprop_cell(blob, off, "d-cache-block-size", dline_size); | |
730b2fcf KG |
183 | fdt_setprop_cell(blob, off, "d-cache-size", dsize); |
184 | fdt_setprop_cell(blob, off, "d-cache-sets", dnum_sets); | |
185 | ||
186 | /* i-side config */ | |
187 | isize = (l1cfg1 & 0x7ff) * 1024; | |
188 | inum_ways = ((l1cfg1 >> 11) & 0xff) + 1; | |
189 | iline_size = (((l1cfg1 >> 23) & 0x3) + 1) * 32; | |
190 | inum_sets = isize / (iline_size * inum_ways); | |
191 | ||
192 | fdt_setprop_cell(blob, off, "i-cache-block-size", iline_size); | |
730b2fcf KG |
193 | fdt_setprop_cell(blob, off, "i-cache-size", isize); |
194 | fdt_setprop_cell(blob, off, "i-cache-sets", inum_sets); | |
195 | ||
196 | off = fdt_node_offset_by_prop_value(blob, off, | |
197 | "device_type", "cpu", 4); | |
198 | } | |
199 | ||
200 | ft_fixup_l2cache(blob); | |
201 | } | |
202 | ||
203 | ||
f852ce72 KG |
204 | void ft_cpu_setup(void *blob, bd_t *bd) |
205 | { | |
6b70ffb9 KP |
206 | /* delete crypto node if not on an E-processor */ |
207 | if (!IS_E_PROCESSOR(get_svr())) | |
208 | fdt_fixup_crypto_node(blob, 0); | |
209 | ||
f852ce72 KG |
210 | #if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\ |
211 | defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) | |
ba37aa03 | 212 | fdt_fixup_ethernet(blob); |
f852ce72 KG |
213 | #endif |
214 | ||
215 | do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, | |
216 | "timebase-frequency", bd->bi_busfreq / 8, 1); | |
217 | do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, | |
218 | "bus-frequency", bd->bi_busfreq, 1); | |
219 | do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, | |
220 | "clock-frequency", bd->bi_intfreq, 1); | |
221 | do_fixup_by_prop_u32(blob, "device_type", "soc", 4, | |
222 | "bus-frequency", bd->bi_busfreq, 1); | |
223 | #ifdef CONFIG_QE | |
69018ce2 | 224 | ft_qe_setup(blob); |
f852ce72 KG |
225 | #endif |
226 | ||
6d0f6bcf | 227 | #ifdef CONFIG_SYS_NS16550 |
f852ce72 | 228 | do_fixup_by_compat_u32(blob, "ns16550", |
6d0f6bcf | 229 | "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); |
f852ce72 KG |
230 | #endif |
231 | ||
232 | #ifdef CONFIG_CPM2 | |
233 | do_fixup_by_compat_u32(blob, "fsl,cpm2-scc-uart", | |
234 | "current-speed", bd->bi_baudrate, 1); | |
235 | ||
236 | do_fixup_by_compat_u32(blob, "fsl,cpm2-brg", | |
237 | "clock-frequency", bd->bi_brgfreq, 1); | |
238 | #endif | |
239 | ||
240 | fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); | |
ec2b74ff KG |
241 | |
242 | #ifdef CONFIG_MP | |
243 | ft_fixup_cpu(blob, (u64)bd->bi_memstart + (u64)bd->bi_memsize); | |
244 | #endif | |
730b2fcf KG |
245 | |
246 | ft_fixup_cache(blob); | |
f852ce72 | 247 | } |