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