source: SVN/rincon/u-boot/cpu/leon3/prom.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 3 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

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