2 * Copyright 2007 Freescale Semiconductor, Inc.
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 * See file CREDITS for list of people who contributed to this
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.
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.
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,
28 #include <fdt_support.h>
29 #include <asm/processor.h>
31 extern void ft_qe_setup(void *blob
);
35 DECLARE_GLOBAL_DATA_PTR
;
37 void ft_fixup_cpu(void *blob
, u64 memory_limit
)
40 ulong spin_tbl_addr
= get_spin_addr();
41 u32 bootpg
, id
= get_my_id();
43 /* if we have 4G or more of memory, put the boot page at 4Gb-4k */
44 if ((u64
)gd
->ram_size
> 0xfffff000)
47 bootpg
= gd
->ram_size
- 4096;
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);
55 fdt_setprop_string(blob
, off
, "status", "okay");
57 u64 val
= *reg
* SIZE_BOOT_ENTRY
+ spin_tbl_addr
;
58 val
= cpu_to_fdt32(val
);
59 fdt_setprop_string(blob
, off
, "status",
61 fdt_setprop_string(blob
, off
, "enable-method",
63 fdt_setprop(blob
, off
, "cpu-release-addr",
67 printf ("cpu NULL\n");
69 off
= fdt_node_offset_by_prop_value(blob
, off
,
70 "device_type", "cpu", 4);
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);
77 printf("%s: %s\n", __FUNCTION__
, fdt_strerror(off
));
82 #ifdef CONFIG_L2_CACHE
83 /* return size in kilobytes */
84 static inline u32
l2cache_size(void)
86 volatile ccsr_l2cache_t
*l2cache
= (void *)CONFIG_SYS_MPC85xx_L2_ADDR
;
87 volatile u32 l2siz_field
= (l2cache
->l2ctl
>> 28) & 0x3;
88 u32 ver
= SVR_SOC_VER(get_svr());
90 switch (l2siz_field
) {
94 if (ver
== SVR_8540
|| ver
== SVR_8560
||
95 ver
== SVR_8541
|| ver
== SVR_8541_E
||
96 ver
== SVR_8555
|| ver
== SVR_8555_E
)
102 if (ver
== SVR_8540
|| ver
== SVR_8560
||
103 ver
== SVR_8541
|| ver
== SVR_8541_E
||
104 ver
== SVR_8555
|| ver
== SVR_8555_E
)
117 static inline void ft_fixup_l2cache(void *blob
)
121 struct cpu_type
*cpu
= identify_cpu(SVR_SOC_VER(get_svr()));
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
);
129 off
= fdt_node_offset_by_prop_value(blob
, -1, "device_type", "cpu", 4);
131 debug("no cpu node fount\n");
135 ph
= (u32
*)fdt_getprop(blob
, off
, "next-level-cache", 0);
138 debug("no next-level-cache property\n");
142 off
= fdt_node_offset_by_phandle(blob
, *ph
);
144 printf("%s: %s\n", __func__
, fdt_strerror(off
));
149 len
= sprintf(compat_buf
, "fsl,mpc%s-l2-cache-controller",
151 sprintf(&compat_buf
[len
+ 1], "cache");
153 fdt_setprop(blob
, off
, "cache-unified", NULL
, 0);
154 fdt_setprop_cell(blob
, off
, "cache-block-size", line_size
);
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
));
161 #define ft_fixup_l2cache(x)
164 static inline void ft_fixup_cache(void *blob
)
168 off
= fdt_node_offset_by_prop_value(blob
, -1, "device_type", "cpu", 4);
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
;
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
);
182 fdt_setprop_cell(blob
, off
, "d-cache-block-size", dline_size
);
183 fdt_setprop_cell(blob
, off
, "d-cache-size", dsize
);
184 fdt_setprop_cell(blob
, off
, "d-cache-sets", dnum_sets
);
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
);
192 fdt_setprop_cell(blob
, off
, "i-cache-block-size", iline_size
);
193 fdt_setprop_cell(blob
, off
, "i-cache-size", isize
);
194 fdt_setprop_cell(blob
, off
, "i-cache-sets", inum_sets
);
196 off
= fdt_node_offset_by_prop_value(blob
, off
,
197 "device_type", "cpu", 4);
200 ft_fixup_l2cache(blob
);
204 void ft_cpu_setup(void *blob
, bd_t
*bd
)
206 /* delete crypto node if not on an E-processor */
207 if (!IS_E_PROCESSOR(get_svr()))
208 fdt_fixup_crypto_node(blob
, 0);
210 #if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\
211 defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3)
212 fdt_fixup_ethernet(blob
);
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);
227 #ifdef CONFIG_SYS_NS16550
228 do_fixup_by_compat_u32(blob
, "ns16550",
229 "clock-frequency", CONFIG_SYS_NS16550_CLK
, 1);
233 do_fixup_by_compat_u32(blob
, "fsl,cpm2-scc-uart",
234 "current-speed", bd
->bi_baudrate
, 1);
236 do_fixup_by_compat_u32(blob
, "fsl,cpm2-brg",
237 "clock-frequency", bd
->bi_brgfreq
, 1);
240 fdt_fixup_memory(blob
, (u64
)bd
->bi_memstart
, (u64
)bd
->bi_memsize
);
243 ft_fixup_cpu(blob
, (u64
)bd
->bi_memstart
+ (u64
)bd
->bi_memsize
);
246 ft_fixup_cache(blob
);