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