Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / arch / sparc / cpu / leon3 / prom.c
1 /* prom.c - emulates a sparc v0 PROM for the linux kernel.
2  *
3  * Copyright (C) 2003 Konrad Eisele <eiselekd@web.de>
4  * Copyright (C) 2004 Stefan Holst <mail@s-holst.de>
5  * Copyright (C) 2007 Daniel Hellstrom <daniel@gaisler.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm/prom.h>
12 #include <asm/machines.h>
13 #include <asm/srmmu.h>
14 #include <asm/processor.h>
15 #include <asm/irq.h>
16 #include <asm/leon.h>
17 #include <ambapp.h>
18
19 #include <config.h>
20 /*
21 #define PRINT_ROM_VEC
22 */
23 extern struct linux_romvec *kernel_arg_promvec;
24 extern ambapp_dev_apbuart *leon3_apbuart;
25
26 #define PROM_PGT __attribute__ ((__section__ (".prom.pgt")))
27 #define PROM_TEXT __attribute__ ((__section__ (".prom.text")))
28 #define PROM_DATA __attribute__ ((__section__ (".prom.data")))
29
30 ambapp_dev_gptimer *gptimer;
31
32 /* for __va */
33 extern int __prom_start;
34 #define PAGE_OFFSET 0xf0000000
35 #define phys_base CONFIG_SYS_SDRAM_BASE
36 #define PROM_OFFS 8192
37 #define PROM_SIZE_MASK (PROM_OFFS-1)
38 #define __va(x) ( \
39         (void *)( ((unsigned long)(x))-PROM_OFFS+ \
40         (CONFIG_SYS_PROM_OFFSET-phys_base)+PAGE_OFFSET-CONFIG_SYS_TEXT_BASE ) \
41         )
42 #define __phy(x) ((void *)(((unsigned long)(x))-PROM_OFFS+CONFIG_SYS_PROM_OFFSET-CONFIG_SYS_TEXT_BASE))
43
44 struct property {
45         char *name;
46         char *value;
47         int length;
48 };
49
50 struct node {
51         int level;
52         struct property *properties;
53 };
54
55 static void leon_reboot(char *bcommand);
56 static void leon_halt(void);
57 static int leon_nbputchar(int c);
58 static int leon_nbgetchar(void);
59
60 static int no_nextnode(int node);
61 static int no_child(int node);
62 static int no_proplen(int node, char *name);
63 static int no_getprop(int node, char *name, char *value);
64 static int no_setprop(int node, char *name, char *value, int len);
65 static char *no_nextprop(int node, char *name);
66
67 static struct property PROM_TEXT *find_property(int node, char *name);
68 static int PROM_TEXT leon_strcmp(const char *s1, const char *s2);
69 static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n);
70 static void PROM_TEXT leon_reboot_physical(char *bcommand);
71
72 void __inline__ leon_flush_cache_all(void)
73 {
74         __asm__ __volatile__(" flush ");
75       __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory");
76 }
77
78 void __inline__ leon_flush_tlb_all(void)
79 {
80         leon_flush_cache_all();
81         __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400),
82                              "i"(ASI_MMUFLUSH):"memory");
83 }
84
85 typedef struct {
86         unsigned int ctx_table[256];
87         unsigned int pgd_table[256];
88 } sparc_srmmu_setup;
89
90 sparc_srmmu_setup srmmu_tables PROM_PGT = {
91         {0},
92         {0x1e,
93          0x10001e,
94          0x20001e,
95          0x30001e,
96          0x40001e,
97          0x50001e,
98          0x60001e,
99          0x70001e,
100          0x80001e,
101          0x90001e,
102          0xa0001e,
103          0xb0001e,
104          0xc0001e,
105          0xd0001e,
106          0xe0001e,
107          0xf0001e,
108          0x100001e,
109          0x110001e,
110          0x120001e,
111          0x130001e,
112          0x140001e,
113          0x150001e,
114          0x160001e,
115          0x170001e,
116          0x180001e,
117          0x190001e,
118          0x1a0001e,
119          0x1b0001e,
120          0x1c0001e,
121          0x1d0001e,
122          0x1e0001e,
123          0x1f0001e,
124          0x200001e,
125          0x210001e,
126          0x220001e,
127          0x230001e,
128          0x240001e,
129          0x250001e,
130          0x260001e,
131          0x270001e,
132          0x280001e,
133          0x290001e,
134          0x2a0001e,
135          0x2b0001e,
136          0x2c0001e,
137          0x2d0001e,
138          0x2e0001e,
139          0x2f0001e,
140          0x300001e,
141          0x310001e,
142          0x320001e,
143          0x330001e,
144          0x340001e,
145          0x350001e,
146          0x360001e,
147          0x370001e,
148          0x380001e,
149          0x390001e,
150          0x3a0001e,
151          0x3b0001e,
152          0x3c0001e,
153          0x3d0001e,
154          0x3e0001e,
155          0x3f0001e,
156          0x400001e,
157          0x410001e,
158          0x420001e,
159          0x430001e,
160          0x440001e,
161          0x450001e,
162          0x460001e,
163          0x470001e,
164          0x480001e,
165          0x490001e,
166          0x4a0001e,
167          0x4b0001e,
168          0x4c0001e,
169          0x4d0001e,
170          0x4e0001e,
171          0x4f0001e,
172          0x500001e,
173          0x510001e,
174          0x520001e,
175          0x530001e,
176          0x540001e,
177          0x550001e,
178          0x560001e,
179          0x570001e,
180          0x580001e,
181          0x590001e,
182          0x5a0001e,
183          0x5b0001e,
184          0x5c0001e,
185          0x5d0001e,
186          0x5e0001e,
187          0x5f0001e,
188          0x600001e,
189          0x610001e,
190          0x620001e,
191          0x630001e,
192          0x640001e,
193          0x650001e,
194          0x660001e,
195          0x670001e,
196          0x680001e,
197          0x690001e,
198          0x6a0001e,
199          0x6b0001e,
200          0x6c0001e,
201          0x6d0001e,
202          0x6e0001e,
203          0x6f0001e,
204          0x700001e,
205          0x710001e,
206          0x720001e,
207          0x730001e,
208          0x740001e,
209          0x750001e,
210          0x760001e,
211          0x770001e,
212          0x780001e,
213          0x790001e,
214          0x7a0001e,
215          0x7b0001e,
216          0x7c0001e,
217          0x7d0001e,
218          0x7e0001e,
219          0x7f0001e,
220          0x800001e,
221          0x810001e,
222          0x820001e,
223          0x830001e,
224          0x840001e,
225          0x850001e,
226          0x860001e,
227          0x870001e,
228          0x880001e,
229          0x890001e,
230          0x8a0001e,
231          0x8b0001e,
232          0x8c0001e,
233          0x8d0001e,
234          0x8e0001e,
235          0x8f0001e,
236          0x900001e,
237          0x910001e,
238          0x920001e,
239          0x930001e,
240          0x940001e,
241          0x950001e,
242          0x960001e,
243          0x970001e,
244          0x980001e,
245          0x990001e,
246          0x9a0001e,
247          0x9b0001e,
248          0x9c0001e,
249          0x9d0001e,
250          0x9e0001e,
251          0x9f0001e,
252          0xa00001e,
253          0xa10001e,
254          0xa20001e,
255          0xa30001e,
256          0xa40001e,
257          0xa50001e,
258          0xa60001e,
259          0xa70001e,
260          0xa80001e,
261          0xa90001e,
262          0xaa0001e,
263          0xab0001e,
264          0xac0001e,
265          0xad0001e,
266          0xae0001e,
267          0xaf0001e,
268          0xb00001e,
269          0xb10001e,
270          0xb20001e,
271          0xb30001e,
272          0xb40001e,
273          0xb50001e,
274          0xb60001e,
275          0xb70001e,
276          0xb80001e,
277          0xb90001e,
278          0xba0001e,
279          0xbb0001e,
280          0xbc0001e,
281          0xbd0001e,
282          0xbe0001e,
283          0xbf0001e,
284          0xc00001e,
285          0xc10001e,
286          0xc20001e,
287          0xc30001e,
288          0xc40001e,
289          0xc50001e,
290          0xc60001e,
291          0xc70001e,
292          0xc80001e,
293          0xc90001e,
294          0xca0001e,
295          0xcb0001e,
296          0xcc0001e,
297          0xcd0001e,
298          0xce0001e,
299          0xcf0001e,
300          0xd00001e,
301          0xd10001e,
302          0xd20001e,
303          0xd30001e,
304          0xd40001e,
305          0xd50001e,
306          0xd60001e,
307          0xd70001e,
308          0xd80001e,
309          0xd90001e,
310          0xda0001e,
311          0xdb0001e,
312          0xdc0001e,
313          0xdd0001e,
314          0xde0001e,
315          0xdf0001e,
316          0xe00001e,
317          0xe10001e,
318          0xe20001e,
319          0xe30001e,
320          0xe40001e,
321          0xe50001e,
322          0xe60001e,
323          0xe70001e,
324          0xe80001e,
325          0xe90001e,
326          0xea0001e,
327          0xeb0001e,
328          0xec0001e,
329          0xed0001e,
330          0xee0001e,
331          0xef0001e,
332          0x400001e              /* default */
333          }
334 };
335
336 /* a self contained prom info structure */
337 struct leon_reloc_func {
338         struct property *(*find_property) (int node, char *name);
339         int (*strcmp) (char *s1, char *s2);
340         void *(*memcpy) (void *dest, const void *src, size_t n);
341         void (*reboot_physical) (char *cmd);
342         ambapp_dev_apbuart *leon3_apbuart;
343 };
344
345 struct leon_prom_info {
346         int freq_khz;
347         int leon_nctx;
348         int mids[32];
349         int baudrates[2];
350         struct leon_reloc_func reloc_funcs;
351         struct property root_properties[4];
352         struct property cpu_properties[7];
353 #undef  CPUENTRY
354 #define CPUENTRY(idx) struct property cpu_properties##idx[4]
355          CPUENTRY(1);
356          CPUENTRY(2);
357          CPUENTRY(3);
358          CPUENTRY(4);
359          CPUENTRY(5);
360          CPUENTRY(6);
361          CPUENTRY(7);
362          CPUENTRY(8);
363          CPUENTRY(9);
364          CPUENTRY(10);
365          CPUENTRY(11);
366          CPUENTRY(12);
367          CPUENTRY(13);
368          CPUENTRY(14);
369          CPUENTRY(15);
370          CPUENTRY(16);
371          CPUENTRY(17);
372          CPUENTRY(18);
373          CPUENTRY(19);
374          CPUENTRY(20);
375          CPUENTRY(21);
376          CPUENTRY(22);
377          CPUENTRY(23);
378          CPUENTRY(24);
379          CPUENTRY(25);
380          CPUENTRY(26);
381          CPUENTRY(27);
382          CPUENTRY(28);
383          CPUENTRY(29);
384          CPUENTRY(30);
385          CPUENTRY(31);
386         struct idprom idprom;
387         struct linux_nodeops nodeops;
388         struct linux_mlist_v0 *totphys_p;
389         struct linux_mlist_v0 totphys;
390         struct linux_mlist_v0 *avail_p;
391         struct linux_mlist_v0 avail;
392         struct linux_mlist_v0 *prommap_p;
393         void (*synchook) (void);
394         struct linux_arguments_v0 *bootargs_p;
395         struct linux_arguments_v0 bootargs;
396         struct linux_romvec romvec;
397         struct node nodes[35];
398         char s_device_type[12];
399         char s_cpu[4];
400         char s_mid[4];
401         char s_idprom[7];
402         char s_compatability[14];
403         char s_leon2[6];
404         char s_mmu_nctx[9];
405         char s_frequency[16];
406         char s_uart1_baud[11];
407         char s_uart2_baud[11];
408         char arg[256];
409 };
410
411 /* static prom info */
412 static struct leon_prom_info PROM_DATA spi = {
413         CONFIG_SYS_CLK_FREQ / 1000,
414         256,
415         {
416 #undef  CPUENTRY
417 #define CPUENTRY(idx) idx
418          CPUENTRY(0),
419          CPUENTRY(1),
420          CPUENTRY(2),
421          CPUENTRY(3),
422          CPUENTRY(4),
423          CPUENTRY(5),
424          CPUENTRY(6),
425          CPUENTRY(7),
426          CPUENTRY(8),
427          CPUENTRY(9),
428          CPUENTRY(10),
429          CPUENTRY(11),
430          CPUENTRY(12),
431          CPUENTRY(13),
432          CPUENTRY(14),
433          CPUENTRY(15),
434          CPUENTRY(16),
435          CPUENTRY(17),
436          CPUENTRY(18),
437          CPUENTRY(19),
438          CPUENTRY(20),
439          CPUENTRY(21),
440          CPUENTRY(22),
441          CPUENTRY(23),
442          CPUENTRY(24),
443          CPUENTRY(25),
444          CPUENTRY(26),
445          CPUENTRY(27),
446          CPUENTRY(28),
447          CPUENTRY(29),
448          CPUENTRY(30),
449          31},
450         {38400, 38400},
451         {
452          __va(find_property),
453          __va(leon_strcmp),
454          __va(leon_memcpy),
455          __phy(leon_reboot_physical),
456          },
457         {
458          {__va(spi.s_device_type), __va(spi.s_idprom), 4},
459          {__va(spi.s_idprom), (char *)__va(&spi.idprom), sizeof(struct idprom)},
460          {__va(spi.s_compatability), __va(spi.s_leon2), 5},
461          {NULL, NULL, -1}
462          },
463         {
464          {__va(spi.s_device_type), __va(spi.s_cpu), 4},
465          {__va(spi.s_mid), __va(&spi.mids[0]), 4},
466          {__va(spi.s_mmu_nctx), (char *)__va(&spi.leon_nctx), 4},
467          {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4},
468          {__va(spi.s_uart1_baud), (char *)__va(&spi.baudrates[0]), 4},
469          {__va(spi.s_uart2_baud), (char *)__va(&spi.baudrates[1]), 4},
470          {NULL, NULL, -1}
471          },
472 #undef  CPUENTRY
473 #define CPUENTRY(idx) \
474         { /* cpu_properties */                                          \
475                 {__va(spi.s_device_type), __va(spi.s_cpu), 4},          \
476                 {__va(spi.s_mid), __va(&spi.mids[idx]), 4},                     \
477                 {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4},        \
478                 {NULL, NULL, -1}                                                \
479         }
480         CPUENTRY(1),
481         CPUENTRY(2),
482         CPUENTRY(3),
483         CPUENTRY(4),
484         CPUENTRY(5),
485         CPUENTRY(6),
486         CPUENTRY(7),
487         CPUENTRY(8),
488         CPUENTRY(9),
489         CPUENTRY(10),
490         CPUENTRY(11),
491         CPUENTRY(12),
492         CPUENTRY(13),
493         CPUENTRY(14),
494         CPUENTRY(15),
495         CPUENTRY(16),
496         CPUENTRY(17),
497         CPUENTRY(18),
498         CPUENTRY(19),
499         CPUENTRY(20),
500         CPUENTRY(21),
501         CPUENTRY(22),
502         CPUENTRY(23),
503         CPUENTRY(24),
504         CPUENTRY(25),
505         CPUENTRY(26),
506         CPUENTRY(27),
507         CPUENTRY(28),
508         CPUENTRY(29),
509         CPUENTRY(30),
510         CPUENTRY(31),
511         {
512          0x01,                  /* format */
513          M_LEON2 | M_LEON2_SOC, /* machine type */
514          {0, 0, 0, 0, 0, 0},    /* eth */
515          0,                     /* date */
516          0,                     /* sernum */
517          0,                     /* checksum */
518          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}       /* reserved */
519          },
520         {
521          __va(no_nextnode),
522          __va(no_child),
523          __va(no_proplen),
524          __va(no_getprop),
525          __va(no_setprop),
526          __va(no_nextprop)
527          },
528         __va(&spi.totphys),
529         {
530          NULL,
531          (char *)CONFIG_SYS_SDRAM_BASE,
532          0,
533          },
534         __va(&spi.avail),
535         {
536          NULL,
537          (char *)CONFIG_SYS_SDRAM_BASE,
538          0,
539          },
540         NULL,                   /* prommap_p */
541         NULL,
542         __va(&spi.bootargs),
543         {
544          {NULL, __va(spi.arg), NULL /*... */ },
545          /*... */
546          },
547         {
548          0,
549          0,                     /* sun4c v0 prom */
550          0, 0,
551          {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)},
552          __va(&spi.nodeops),
553          NULL, {NULL /* ... */ },
554          NULL, NULL,
555          NULL, NULL,            /* pv_getchar, pv_putchar */
556          __va(leon_nbgetchar), __va(leon_nbputchar),
557          NULL,
558          __va(leon_reboot),
559          NULL,
560          NULL,
561          NULL,
562          __va(leon_halt),
563          __va(&spi.synchook),
564          {NULL},
565          __va(&spi.bootargs_p)
566          /*... */
567          },
568         {
569          {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ },
570          {0, __va(spi.root_properties)},
571          /* cpu 0, must be spi.nodes[2] see leon_prom_init() */
572          {1, __va(spi.cpu_properties)},
573
574 #undef  CPUENTRY
575 #define CPUENTRY(idx) \
576           {1, __va(spi.cpu_properties##idx) }   /* cpu <idx> */
577          CPUENTRY(1),
578          CPUENTRY(2),
579          CPUENTRY(3),
580          CPUENTRY(4),
581          CPUENTRY(5),
582          CPUENTRY(6),
583          CPUENTRY(7),
584          CPUENTRY(8),
585          CPUENTRY(9),
586          CPUENTRY(10),
587          CPUENTRY(11),
588          CPUENTRY(12),
589          CPUENTRY(13),
590          CPUENTRY(14),
591          CPUENTRY(15),
592          CPUENTRY(16),
593          CPUENTRY(17),
594          CPUENTRY(18),
595          CPUENTRY(19),
596          CPUENTRY(20),
597          CPUENTRY(21),
598          CPUENTRY(22),
599          CPUENTRY(23),
600          CPUENTRY(24),
601          CPUENTRY(25),
602          CPUENTRY(26),
603          CPUENTRY(27),
604          CPUENTRY(28),
605          CPUENTRY(29),
606          CPUENTRY(30),
607          CPUENTRY(31),
608          {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }
609          },
610         "device_type",
611         "cpu",
612         "mid",
613         "idprom",
614         "compatability",
615         "leon2",
616         "mmu-nctx",
617         "clock-frequency",
618         "uart1_baud",
619         "uart2_baud",
620         CONFIG_DEFAULT_KERNEL_COMMAND_LINE
621 };
622
623 /* from arch/sparc/kernel/setup.c */
624 #define RAMDISK_LOAD_FLAG 0x4000
625 extern unsigned short root_flags;
626 extern unsigned short root_dev;
627 extern unsigned short ram_flags;
628 extern unsigned int sparc_ramdisk_image;
629 extern unsigned int sparc_ramdisk_size;
630 extern int root_mountflags;
631
632 extern char initrd_end, initrd_start;
633
634 /* Reboot the CPU = jump to beginning of flash again.
635  *
636  * Make sure that all function are inlined here.
637  */
638 static void PROM_TEXT leon_reboot(char *bcommand)
639 {
640         register char *arg = bcommand;
641         void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd);
642
643         /* get physical address */
644         struct leon_prom_info *pspi =
645             (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
646
647         unsigned int *srmmu_ctx_table;
648
649         /* Turn of Interrupts */
650         set_pil(0xf);
651
652         /* Set kernel's context, context zero */
653         srmmu_set_context(0);
654
655         /* Get physical address of the MMU shutdown routine */
656         reboot_physical = (void *)
657             SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical);
658
659         /* Now that we know the physical address of the function
660          * we can make the MMU allow jumping to it.
661          */
662         srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr();
663
664         srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table);
665
666         /* get physical address of kernel's context table (assume ptd) */
667         srmmu_ctx_table = (unsigned int *)
668             (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4);
669
670         /* enable access to physical address of MMU shutdown function */
671         SPARC_BYPASS_WRITE(&srmmu_ctx_table
672                            [((unsigned int)reboot_physical) >> 24],
673                            (((unsigned int)reboot_physical & 0xff000000) >> 4) |
674                            0x1e);
675
676         /* flush TLB cache */
677         leon_flush_tlb_all();
678
679         /* flash instruction & data cache */
680         sparc_icache_flush_all();
681         sparc_dcache_flush_all();
682
683         /* jump to physical address function
684          * so that when the MMU is disabled
685          * we can continue to execute
686          */
687         reboot_physical(arg);
688 }
689
690 static void PROM_TEXT leon_reboot_physical(char *bcommand)
691 {
692         void __attribute__ ((noreturn)) (*reset) (void);
693
694         /* Turn off MMU */
695         srmmu_set_mmureg(0);
696
697         /* Hardcoded start address */
698         reset = CONFIG_SYS_MONITOR_BASE;
699
700         /* flush data cache */
701         sparc_dcache_flush_all();
702
703         /* flush instruction cache */
704         sparc_icache_flush_all();
705
706         /* Jump to start in Flash */
707         reset();
708 }
709
710 static void PROM_TEXT leon_halt(void)
711 {
712         while (1) ;
713 }
714
715 /* get single char, don't care for blocking*/
716 static int PROM_TEXT leon_nbgetchar(void)
717 {
718         return -1;
719 }
720
721 /* put single char, don't care for blocking*/
722 static int PROM_TEXT leon_nbputchar(int c)
723 {
724         ambapp_dev_apbuart *uart;
725
726         /* get physical address */
727         struct leon_prom_info *pspi =
728             (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
729
730         uart = (ambapp_dev_apbuart *)
731             SPARC_BYPASS_READ(&pspi->reloc_funcs.leon3_apbuart);
732
733         /* no UART? */
734         if (!uart)
735                 return 0;
736
737         /***** put char in buffer... ***********
738          * Make sure all functions are inline! *
739          ***************************************/
740
741         /* Wait for last character to go. */
742         while (!(SPARC_BYPASS_READ(&uart->status)
743                  & LEON_REG_UART_STATUS_THE)) ;
744
745         /* Send data */
746         SPARC_BYPASS_WRITE(&uart->data, c);
747
748         /* Wait for data to be sent */
749         while (!(SPARC_BYPASS_READ(&uart->status)
750                  & LEON_REG_UART_STATUS_TSE)) ;
751
752         return 0;
753 }
754
755 /* node ops */
756
757 /*#define nodes ((struct node *)__va(&pspi->nodes))*/
758 #define nodes ((struct node *)(pspi->nodes))
759
760 static int PROM_TEXT no_nextnode(int node)
761 {
762         /* get physical address */
763         struct leon_prom_info *pspi =
764             (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
765
766         /* convert into virtual address */
767         pspi = (struct leon_prom_info *)
768             (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
769
770         if (nodes[node].level == nodes[node + 1].level)
771                 return node + 1;
772         return -1;
773 }
774
775 static int PROM_TEXT no_child(int node)
776 {
777         /* get physical address */
778         struct leon_prom_info *pspi = (struct leon_prom_info *)
779             (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
780
781         /* convert into virtual address */
782         pspi = (struct leon_prom_info *)
783             (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
784
785         if (nodes[node].level == nodes[node + 1].level - 1)
786                 return node + 1;
787         return -1;
788 }
789
790 static struct property PROM_TEXT *find_property(int node, char *name)
791 {
792         /* get physical address */
793         struct leon_prom_info *pspi = (struct leon_prom_info *)
794             (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
795
796         /* convert into virtual address */
797         pspi = (struct leon_prom_info *)
798             (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
799
800         struct property *prop = &nodes[node].properties[0];
801         while (prop && prop->name) {
802                 if (pspi->reloc_funcs.strcmp(prop->name, name) == 0)
803                         return prop;
804                 prop++;
805         }
806         return NULL;
807 }
808
809 static int PROM_TEXT no_proplen(int node, char *name)
810 {
811         /* get physical address */
812         struct leon_prom_info *pspi = (struct leon_prom_info *)
813             (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
814
815         /* convert into virtual address */
816         pspi = (struct leon_prom_info *)
817             (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
818
819         struct property *prop = pspi->reloc_funcs.find_property(node, name);
820         if (prop)
821                 return prop->length;
822         return -1;
823 }
824
825 static int PROM_TEXT no_getprop(int node, char *name, char *value)
826 {
827         /* get physical address */
828         struct leon_prom_info *pspi = (struct leon_prom_info *)
829             (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
830
831         /* convert into virtual address */
832         pspi = (struct leon_prom_info *)
833             (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
834
835         struct property *prop = pspi->reloc_funcs.find_property(node, name);
836         if (prop) {
837                 pspi->reloc_funcs.memcpy(value, prop->value, prop->length);
838                 return 1;
839         }
840         return -1;
841 }
842
843 static int PROM_TEXT no_setprop(int node, char *name, char *value, int len)
844 {
845         return -1;
846 }
847
848 static char PROM_TEXT *no_nextprop(int node, char *name)
849 {
850         /* get physical address */
851         struct leon_prom_info *pspi = (struct leon_prom_info *)
852             (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
853         struct property *prop;
854
855         /* convert into virtual address */
856         pspi = (struct leon_prom_info *)
857             (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
858
859         if (!name || !name[0])
860                 return nodes[node].properties[0].name;
861
862         prop = pspi->reloc_funcs.find_property(node, name);
863         if (prop)
864                 return prop[1].name;
865         return NULL;
866 }
867
868 static int PROM_TEXT leon_strcmp(const char *s1, const char *s2)
869 {
870         register char result;
871
872         while (1) {
873                 result = *s1 - *s2;
874                 if (result || !*s1)
875                         break;
876                 s2++;
877                 s1++;
878         }
879
880         return result;
881 }
882
883 static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n)
884 {
885         char *dst = (char *)dest, *source = (char *)src;
886
887         while (n--) {
888                 *dst = *source;
889                 dst++;
890                 source++;
891         }
892         return dest;
893 }
894
895 #define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp))
896
897 void leon_prom_init(struct leon_prom_info *pspi)
898 {
899         unsigned long i;
900         unsigned char cksum, *ptr;
901         char *addr_str, *end;
902         unsigned long sp;
903         GETREGSP(sp);
904
905         pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000;
906
907         /* Set Available main memory size */
908         pspi->totphys.num_bytes = CONFIG_SYS_PROM_OFFSET - CONFIG_SYS_SDRAM_BASE;
909         pspi->avail.num_bytes = pspi->totphys.num_bytes;
910
911         /* Set the pointer to the Console UART in romvec */
912         pspi->reloc_funcs.leon3_apbuart = leon3_apbuart;
913
914         {
915                 int j = 1;
916 #ifdef CONFIG_SMP
917                 ambapp_dev_irqmp *b;
918                 b = (ambapp_dev_irqmp *) leon3_getapbbase(VENDOR_GAISLER,
919                                                           GAISLER_IRQMP);
920                 if (b) {
921                         j = 1 + ((LEON3_BYPASS_LOAD_PA(&(b->mpstatus))
922                                   >> LEON3_IRQMPSTATUS_CPUNR) & 0xf);
923                 }
924 #endif
925 #undef nodes
926                 pspi->nodes[2 + j].level = -1;
927                 pspi->nodes[2 + j].properties = __va(spi.root_properties + 3);
928         }
929
930         /* Set Ethernet MAC address from environment */
931         if ((addr_str = getenv("ethaddr")) != NULL) {
932                 for (i = 0; i < 6; i++) {
933                         pspi->idprom.id_ethaddr[i] = addr_str ?
934                             simple_strtoul(addr_str, &end, 16) : 0;
935                         if (addr_str) {
936                                 addr_str = (*end) ? end + 1 : end;
937                         }
938                 }
939         } else {
940                 /* HW Address not found in environment,
941                  * Set default HW address
942                  */
943                 pspi->idprom.id_ethaddr[0] = 0;
944                 pspi->idprom.id_ethaddr[1] = 0;
945                 pspi->idprom.id_ethaddr[2] = 0;
946                 pspi->idprom.id_ethaddr[3] = 0;
947                 pspi->idprom.id_ethaddr[4] = 0;
948                 pspi->idprom.id_ethaddr[5] = 0;
949         }
950
951         ptr = (unsigned char *)&pspi->idprom;
952         for (i = cksum = 0; i <= 0x0E; i++)
953                 cksum ^= *ptr++;
954         pspi->idprom.id_cksum = cksum;
955 }
956
957 static inline void set_cache(unsigned long regval)
958 {
959         asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory");
960 }
961
962 extern unsigned short bss_start, bss_end;
963
964 /* mark as section .img.main.text, to be referenced in linker script */
965 int prom_init(void)
966 {
967         struct leon_prom_info *pspi = (void *)
968             ((((unsigned int)&spi) & PROM_SIZE_MASK) + CONFIG_SYS_PROM_OFFSET);
969
970         /* disable mmu */
971         srmmu_set_mmureg(0x00000000);
972         __asm__ __volatile__("flush\n\t");
973
974         /* init prom info struct */
975         leon_prom_init(pspi);
976
977         kernel_arg_promvec = &pspi->romvec;
978 #ifdef PRINT_ROM_VEC
979         printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec));
980 #endif
981         return 0;
982 }
983
984 /* Copy current kernel boot argument to ROMvec */
985 void prepare_bootargs(char *bootargs)
986 {
987         struct leon_prom_info *pspi;
988         char *src, *dst;
989         int left;
990
991         /* if no bootargs set, skip copying ==> default bootline */
992         if (bootargs && (*bootargs != '\0')) {
993                 pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) +
994                                 CONFIG_SYS_PROM_OFFSET);
995                 src = bootargs;
996                 dst = &pspi->arg[0];
997                 left = 255;     /* max len */
998                 while (*src && left > 0) {
999                         *dst++ = *src++;
1000                         left--;
1001                 }
1002                 /* terminate kernel command line string */
1003                 *dst = 0;
1004         }
1005 }
1006
1007 void srmmu_init_cpu(unsigned int entry)
1008 {
1009         sparc_srmmu_setup *psrmmu_tables = (void *)
1010             ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) +
1011              CONFIG_SYS_PROM_OFFSET);
1012
1013         /* Make context 0 (kernel's context) point
1014          * to our prepared memory mapping
1015          */
1016 #define PTD 1
1017         psrmmu_tables->ctx_table[0] =
1018             ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD;
1019
1020         /* Set virtual kernel address 0xf0000000
1021          * to SRAM/SDRAM address.
1022          * Make it READ/WRITE/EXEC to SuperUser
1023          */
1024 #define PTE 2
1025 #define ACC_SU_ALL 0x1c
1026         psrmmu_tables->pgd_table[0xf0] =
1027             (CONFIG_SYS_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE;
1028         psrmmu_tables->pgd_table[0xf1] =
1029             ((CONFIG_SYS_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE;
1030         psrmmu_tables->pgd_table[0xf2] =
1031             ((CONFIG_SYS_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE;
1032         psrmmu_tables->pgd_table[0xf3] =
1033             ((CONFIG_SYS_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE;
1034         psrmmu_tables->pgd_table[0xf4] =
1035             ((CONFIG_SYS_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE;
1036         psrmmu_tables->pgd_table[0xf5] =
1037             ((CONFIG_SYS_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE;
1038         psrmmu_tables->pgd_table[0xf6] =
1039             ((CONFIG_SYS_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE;
1040         psrmmu_tables->pgd_table[0xf7] =
1041             ((CONFIG_SYS_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE;
1042
1043         /* convert rom vec pointer to virtual address */
1044         kernel_arg_promvec = (struct linux_romvec *)
1045             (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000);
1046
1047         /* Set Context pointer to point to context table
1048          * 256 contexts supported.
1049          */
1050         srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]);
1051
1052         /* Set kernel's context, context zero */
1053         srmmu_set_context(0);
1054
1055         /* Invalidate all Cache */
1056         __asm__ __volatile__("flush\n\t");
1057
1058         srmmu_set_mmureg(0x00000001);
1059         leon_flush_tlb_all();
1060         leon_flush_cache_all();
1061 }