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