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