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