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