1
2
3
4
5
6
7#include <common.h>
8#include <command.h>
9#include <cpu_func.h>
10#include <dm.h>
11#include <env.h>
12#include <init.h>
13#include <log.h>
14#include <net.h>
15#include <pci.h>
16#include <time.h>
17#include <dm/simple_bus.h>
18#include <dm/uclass-internal.h>
19#include <asm/global_data.h>
20#include <asm/processor.h>
21#include <asm/mmu.h>
22#include <asm/fsl_pci.h>
23#include <asm/io.h>
24#include <linux/libfdt.h>
25#include <fdt_support.h>
26#include <netdev.h>
27#include <fdtdec.h>
28#include <errno.h>
29#include <malloc.h>
30#include <virtio_types.h>
31#include <virtio.h>
32
33DECLARE_GLOBAL_DATA_PTR;
34
35
36#define SYS_PCI_MAP_START 0x80000000
37#define SYS_PCI_MAP_END 0xe0000000
38
39static void *get_fdt_virt(void)
40{
41 if (gd->flags & GD_FLG_RELOC)
42 return (void *)gd->fdt_blob;
43 else
44 return (void *)CFG_SYS_TMPVIRT;
45}
46
47static uint64_t get_fdt_phys(void)
48{
49 return (uint64_t)(uintptr_t)gd->fdt_blob;
50}
51
52static void map_fdt_as(int esel)
53{
54 u32 mas0, mas1, mas2, mas3, mas7;
55 uint64_t fdt_phys = get_fdt_phys();
56 unsigned long fdt_phys_tlb = fdt_phys & ~0xffffful;
57 unsigned long fdt_virt_tlb = (ulong)get_fdt_virt() & ~0xffffful;
58
59 mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(esel);
60 mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_1M);
61 mas2 = FSL_BOOKE_MAS2(fdt_virt_tlb, 0);
62 mas3 = FSL_BOOKE_MAS3(fdt_phys_tlb, 0, MAS3_SW|MAS3_SR);
63 mas7 = FSL_BOOKE_MAS7(fdt_phys_tlb);
64
65 write_tlb(mas0, mas1, mas2, mas3, mas7);
66}
67
68uint64_t get_phys_ccsrbar_addr_early(void)
69{
70 void *fdt = get_fdt_virt();
71 uint64_t r;
72 int size, node;
73 u32 naddr;
74 const fdt32_t *prop;
75
76
77
78
79
80 map_fdt_as(10);
81 node = fdt_path_offset(fdt, "/soc");
82 naddr = fdt_address_cells(fdt, node);
83 prop = fdt_getprop(fdt, node, "ranges", &size);
84 r = fdt_translate_address(fdt, node, prop + naddr);
85 disable_tlb(10);
86
87 return r;
88}
89
90int checkboard(void)
91{
92 return 0;
93}
94
95static int pci_map_region(phys_addr_t paddr, phys_size_t size, ulong *pmap_addr)
96{
97 ulong map_addr;
98
99 if (!pmap_addr)
100 return 0;
101
102 map_addr = *pmap_addr;
103
104
105 map_addr += size - 1;
106 map_addr &= ~(size - 1);
107
108 if (map_addr + size >= SYS_PCI_MAP_END)
109 return -1;
110
111
112 assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
113 *pmap_addr = map_addr + size;
114
115 return 0;
116}
117
118static void platform_bus_map_region(ulong map_addr, phys_addr_t paddr,
119 phys_size_t size)
120{
121
122 map_addr += size - 1;
123 map_addr &= ~(size - 1);
124
125
126 assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
127}
128
129int misc_init_r(void)
130{
131 struct udevice *dev;
132 struct pci_region *io;
133 struct pci_region *mem;
134 struct pci_region *pre;
135 ulong map_addr;
136 int ret;
137
138
139 uclass_first_device(UCLASS_PCI, &dev);
140
141 pci_get_regions(dev, &io, &mem, &pre);
142
143
144 map_addr = SYS_PCI_MAP_START;
145
146
147 ret = pci_map_region(mem->phys_start, mem->size, &map_addr);
148 if (ret)
149 return ret;
150
151
152 ret = pci_map_region(io->phys_start, io->size, &map_addr);
153 if (ret)
154 return ret;
155
156
157
158
159
160 virtio_init();
161
162
163
164
165
166 disable_tlb(find_tlb_idx((void *)CFG_SYS_TMPVIRT, 1));
167
168
169
170
171
172 for (ret = uclass_find_first_device(UCLASS_SIMPLE_BUS, &dev);
173 dev;
174 ret = uclass_find_next_device(&dev)) {
175 if (device_is_compatible(dev, "qemu,platform")) {
176 struct simple_bus_plat *plat = dev_get_uclass_plat(dev);
177
178 platform_bus_map_region(CONFIG_PLATFORM_BUS_MAP_ADDR,
179 plat->target, plat->size);
180 break;
181 }
182 }
183
184 return 0;
185}
186
187int last_stage_init(void)
188{
189 void *fdt = get_fdt_virt();
190 int len = 0;
191 const uint64_t *prop;
192 int chosen;
193
194 chosen = fdt_path_offset(fdt, "/chosen");
195 if (chosen < 0) {
196 printf("Couldn't find /chosen node in fdt\n");
197 return -EIO;
198 }
199
200
201 prop = fdt_getprop(fdt, chosen, "qemu,boot-kernel", &len);
202 if (prop && (len >= 8))
203 env_set_hex("qemu_kernel_addr", *prop);
204
205 return 0;
206}
207
208static uint64_t get_linear_ram_size(void)
209{
210 void *fdt = get_fdt_virt();
211 const void *prop;
212 int memory;
213 int len;
214
215 memory = fdt_path_offset(fdt, "/memory");
216 prop = fdt_getprop(fdt, memory, "reg", &len);
217
218 if (prop && len >= 16)
219 return *(uint64_t *)(prop+8);
220
221 panic("Couldn't determine RAM size");
222}
223
224phys_size_t fsl_ddr_sdram_size(void)
225{
226 return get_linear_ram_size();
227}
228
229void init_tlbs(void)
230{
231 phys_size_t ram_size;
232
233
234
235
236
237
238
239 map_fdt_as(0);
240
241
242 ram_size = get_linear_ram_size();
243
244
245 disable_tlb(0);
246
247
248 init_used_tlb_cams();
249
250
251 assert(!tlb_map_range(CFG_SYS_CCSRBAR, CFG_SYS_CCSRBAR_PHYS,
252 1024 * 1024, TLB_MAP_IO));
253
254
255 setup_ddr_tlbs(ram_size >> 20);
256
257
258 assert(!tlb_map_range((ulong)get_fdt_virt(), get_fdt_phys(),
259 1024 * 1024, TLB_MAP_RAM));
260}
261
262static uint32_t get_cpu_freq(void)
263{
264 void *fdt = get_fdt_virt();
265 int cpus_node = fdt_path_offset(fdt, "/cpus");
266 int cpu_node = fdt_first_subnode(fdt, cpus_node);
267 const char *prop = "clock-frequency";
268 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
269}
270
271void get_sys_info(sys_info_t *sys_info)
272{
273 int freq = get_cpu_freq();
274
275 memset(sys_info, 0, sizeof(sys_info_t));
276 sys_info->freq_systembus = freq;
277 sys_info->freq_ddrbus = freq;
278 sys_info->freq_processor[0] = freq;
279}
280
281int get_clocks(void)
282{
283 sys_info_t sys_info;
284
285 get_sys_info(&sys_info);
286
287 gd->cpu_clk = sys_info.freq_processor[0];
288 gd->bus_clk = sys_info.freq_systembus;
289 gd->mem_clk = sys_info.freq_ddrbus;
290 gd->arch.lbc_clk = sys_info.freq_ddrbus;
291
292 return 0;
293}
294
295unsigned long get_tbclk(void)
296{
297 void *fdt = get_fdt_virt();
298 int cpus_node = fdt_path_offset(fdt, "/cpus");
299 int cpu_node = fdt_first_subnode(fdt, cpus_node);
300 const char *prop = "timebase-frequency";
301 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
302}
303
304
305
306
307
308ulong get_bus_freq(ulong dummy)
309{
310 sys_info_t sys_info;
311 get_sys_info(&sys_info);
312 return sys_info.freq_systembus;
313}
314
315
316
317
318int cpu_numcores(void)
319{
320
321
322
323
324 return 1;
325}
326
327
328
329
330u32 cpu_mask(void)
331{
332 return (1 << cpu_numcores()) - 1;
333}
334
335
336
337
338
339
340void *board_fdt_blob_setup(int *err)
341{
342 *err = 0;
343 return get_fdt_virt();
344}
345
346
347int get_serial_clock(void)
348{
349 return get_bus_freq(0);
350}
351