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