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