linux/arch/xtensa/kernel/setup.c
<<
>>
Prefs
   1/*
   2 * arch/xtensa/kernel/setup.c
   3 *
   4 * This file is subject to the terms and conditions of the GNU General Public
   5 * License.  See the file "COPYING" in the main directory of this archive
   6 * for more details.
   7 *
   8 * Copyright (C) 1995  Linus Torvalds
   9 * Copyright (C) 2001 - 2005  Tensilica Inc.
  10 *
  11 * Chris Zankel <chris@zankel.net>
  12 * Joe Taylor   <joe@tensilica.com, joetylr@yahoo.com>
  13 * Kevin Chea
  14 * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
  15 */
  16
  17#include <linux/errno.h>
  18#include <linux/init.h>
  19#include <linux/proc_fs.h>
  20#include <linux/screen_info.h>
  21#include <linux/bootmem.h>
  22#include <linux/kernel.h>
  23
  24#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
  25# include <linux/console.h>
  26#endif
  27
  28#ifdef CONFIG_RTC
  29# include <linux/timex.h>
  30#endif
  31
  32#ifdef CONFIG_PROC_FS
  33# include <linux/seq_file.h>
  34#endif
  35
  36#include <asm/system.h>
  37#include <asm/bootparam.h>
  38#include <asm/pgtable.h>
  39#include <asm/processor.h>
  40#include <asm/timex.h>
  41#include <asm/platform.h>
  42#include <asm/page.h>
  43#include <asm/setup.h>
  44#include <asm/param.h>
  45
  46#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
  47struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
  48#endif
  49
  50#ifdef CONFIG_BLK_DEV_FD
  51extern struct fd_ops no_fd_ops;
  52struct fd_ops *fd_ops;
  53#endif
  54
  55#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
  56extern struct ide_ops no_ide_ops;
  57struct ide_ops *ide_ops;
  58#endif
  59
  60extern struct rtc_ops no_rtc_ops;
  61struct rtc_ops *rtc_ops;
  62
  63#ifdef CONFIG_BLK_DEV_INITRD
  64extern void *initrd_start;
  65extern void *initrd_end;
  66extern void *__initrd_start;
  67extern void *__initrd_end;
  68int initrd_is_mapped = 0;
  69extern int initrd_below_start_ok;
  70#endif
  71
  72unsigned char aux_device_present;
  73extern unsigned long loops_per_jiffy;
  74
  75/* Command line specified as configuration option. */
  76
  77static char __initdata command_line[COMMAND_LINE_SIZE];
  78
  79#ifdef CONFIG_CMDLINE_BOOL
  80static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
  81#endif
  82
  83sysmem_info_t __initdata sysmem;
  84
  85#ifdef CONFIG_BLK_DEV_INITRD
  86int initrd_is_mapped;
  87#endif
  88
  89extern void init_mmu(void);
  90
  91/*
  92 * Boot parameter parsing.
  93 *
  94 * The Xtensa port uses a list of variable-sized tags to pass data to
  95 * the kernel. The first tag must be a BP_TAG_FIRST tag for the list
  96 * to be recognised. The list is terminated with a zero-sized
  97 * BP_TAG_LAST tag.
  98 */
  99
 100typedef struct tagtable {
 101        u32 tag;
 102        int (*parse)(const bp_tag_t*);
 103} tagtable_t;
 104
 105#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn           \
 106        __attribute__((unused, __section__(".taglist"))) = { tag, fn }
 107
 108/* parse current tag */
 109
 110static int __init parse_tag_mem(const bp_tag_t *tag)
 111{
 112        meminfo_t *mi = (meminfo_t*)(tag->data);
 113
 114        if (mi->type != MEMORY_TYPE_CONVENTIONAL)
 115                return -1;
 116
 117        if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
 118                printk(KERN_WARNING
 119                       "Ignoring memory bank 0x%08lx size %ldKB\n",
 120                       (unsigned long)mi->start,
 121                       (unsigned long)mi->end - (unsigned long)mi->start);
 122                return -EINVAL;
 123        }
 124        sysmem.bank[sysmem.nr_banks].type  = mi->type;
 125        sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
 126        sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_SIZE;
 127        sysmem.nr_banks++;
 128
 129        return 0;
 130}
 131
 132__tagtable(BP_TAG_MEMORY, parse_tag_mem);
 133
 134#ifdef CONFIG_BLK_DEV_INITRD
 135
 136static int __init parse_tag_initrd(const bp_tag_t* tag)
 137{
 138        meminfo_t* mi;
 139        mi = (meminfo_t*)(tag->data);
 140        initrd_start = (void*)(mi->start);
 141        initrd_end = (void*)(mi->end);
 142
 143        return 0;
 144}
 145
 146__tagtable(BP_TAG_INITRD, parse_tag_initrd);
 147
 148#endif /* CONFIG_BLK_DEV_INITRD */
 149
 150static int __init parse_tag_cmdline(const bp_tag_t* tag)
 151{
 152        strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE);
 153        command_line[COMMAND_LINE_SIZE - 1] = '\0';
 154        return 0;
 155}
 156
 157__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
 158
 159static int __init parse_bootparam(const bp_tag_t* tag)
 160{
 161        extern tagtable_t __tagtable_begin, __tagtable_end;
 162        tagtable_t *t;
 163
 164        /* Boot parameters must start with a BP_TAG_FIRST tag. */
 165
 166        if (tag->id != BP_TAG_FIRST) {
 167                printk(KERN_WARNING "Invalid boot parameters!\n");
 168                return 0;
 169        }
 170
 171        tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
 172
 173        /* Parse all tags. */
 174
 175        while (tag != NULL && tag->id != BP_TAG_LAST) {
 176                for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
 177                        if (tag->id == t->tag) {
 178                                t->parse(tag);
 179                                break;
 180                        }
 181                }
 182                if (t == &__tagtable_end)
 183                        printk(KERN_WARNING "Ignoring tag "
 184                               "0x%08x\n", tag->id);
 185                tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
 186        }
 187
 188        return 0;
 189}
 190
 191/*
 192 * Initialize architecture. (Early stage)
 193 */
 194
 195void __init init_arch(bp_tag_t *bp_start)
 196{
 197
 198#ifdef CONFIG_BLK_DEV_INITRD
 199        initrd_start = &__initrd_start;
 200        initrd_end = &__initrd_end;
 201#endif
 202
 203        sysmem.nr_banks = 0;
 204
 205#ifdef CONFIG_CMDLINE_BOOL
 206        strcpy(command_line, default_command_line);
 207#endif
 208
 209        /* Parse boot parameters */
 210
 211        if (bp_start)
 212          parse_bootparam(bp_start);
 213
 214        if (sysmem.nr_banks == 0) {
 215                sysmem.nr_banks = 1;
 216                sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
 217                sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
 218                                     + PLATFORM_DEFAULT_MEM_SIZE;
 219        }
 220
 221        /* Early hook for platforms */
 222
 223        platform_init(bp_start);
 224
 225        /* Initialize MMU. */
 226
 227        init_mmu();
 228}
 229
 230/*
 231 * Initialize system. Setup memory and reserve regions.
 232 */
 233
 234extern char _end;
 235extern char _stext;
 236extern char _WindowVectors_text_start;
 237extern char _WindowVectors_text_end;
 238extern char _DebugInterruptVector_literal_start;
 239extern char _DebugInterruptVector_text_end;
 240extern char _KernelExceptionVector_literal_start;
 241extern char _KernelExceptionVector_text_end;
 242extern char _UserExceptionVector_literal_start;
 243extern char _UserExceptionVector_text_end;
 244extern char _DoubleExceptionVector_literal_start;
 245extern char _DoubleExceptionVector_text_end;
 246
 247void __init setup_arch(char **cmdline_p)
 248{
 249        extern int mem_reserve(unsigned long, unsigned long, int);
 250        extern void bootmem_init(void);
 251
 252        memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 253        boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 254        *cmdline_p = command_line;
 255
 256        /* Reserve some memory regions */
 257
 258#ifdef CONFIG_BLK_DEV_INITRD
 259        if (initrd_start < initrd_end) {
 260                initrd_is_mapped = mem_reserve(__pa(initrd_start),
 261                                               __pa(initrd_end), 0);
 262                initrd_below_start_ok = 1;
 263        } else {
 264                initrd_start = 0;
 265        }
 266#endif
 267
 268        mem_reserve(__pa(&_stext),__pa(&_end), 1);
 269
 270        mem_reserve(__pa(&_WindowVectors_text_start),
 271                    __pa(&_WindowVectors_text_end), 0);
 272
 273        mem_reserve(__pa(&_DebugInterruptVector_literal_start),
 274                    __pa(&_DebugInterruptVector_text_end), 0);
 275
 276        mem_reserve(__pa(&_KernelExceptionVector_literal_start),
 277                    __pa(&_KernelExceptionVector_text_end), 0);
 278
 279        mem_reserve(__pa(&_UserExceptionVector_literal_start),
 280                    __pa(&_UserExceptionVector_text_end), 0);
 281
 282        mem_reserve(__pa(&_DoubleExceptionVector_literal_start),
 283                    __pa(&_DoubleExceptionVector_text_end), 0);
 284
 285        bootmem_init();
 286
 287        platform_setup(cmdline_p);
 288
 289
 290        paging_init();
 291
 292#ifdef CONFIG_VT
 293# if defined(CONFIG_VGA_CONSOLE)
 294        conswitchp = &vga_con;
 295# elif defined(CONFIG_DUMMY_CONSOLE)
 296        conswitchp = &dummy_con;
 297# endif
 298#endif
 299
 300#ifdef CONFIG_PCI
 301        platform_pcibios_init();
 302#endif
 303}
 304
 305void machine_restart(char * cmd)
 306{
 307        platform_restart();
 308}
 309
 310void machine_halt(void)
 311{
 312        platform_halt();
 313        while (1);
 314}
 315
 316void machine_power_off(void)
 317{
 318        platform_power_off();
 319        while (1);
 320}
 321#ifdef CONFIG_PROC_FS
 322
 323/*
 324 * Display some core information through /proc/cpuinfo.
 325 */
 326
 327static int
 328c_show(struct seq_file *f, void *slot)
 329{
 330        /* high-level stuff */
 331        seq_printf(f,"processor\t: 0\n"
 332                     "vendor_id\t: Tensilica\n"
 333                     "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
 334                     "core ID\t\t: " XCHAL_CORE_ID "\n"
 335                     "build ID\t: 0x%x\n"
 336                     "byte order\t: %s\n"
 337                     "cpu MHz\t\t: %lu.%02lu\n"
 338                     "bogomips\t: %lu.%02lu\n",
 339                     XCHAL_BUILD_UNIQUE_ID,
 340                     XCHAL_HAVE_BE ?  "big" : "little",
 341                     CCOUNT_PER_JIFFY/(1000000/HZ),
 342                     (CCOUNT_PER_JIFFY/(10000/HZ)) % 100,
 343                     loops_per_jiffy/(500000/HZ),
 344                     (loops_per_jiffy/(5000/HZ)) % 100);
 345
 346        seq_printf(f,"flags\t\t: "
 347#if XCHAL_HAVE_NMI
 348                     "nmi "
 349#endif
 350#if XCHAL_HAVE_DEBUG
 351                     "debug "
 352# if XCHAL_HAVE_OCD
 353                     "ocd "
 354# endif
 355#endif
 356#if XCHAL_HAVE_DENSITY
 357                     "density "
 358#endif
 359#if XCHAL_HAVE_BOOLEANS
 360                     "boolean "
 361#endif
 362#if XCHAL_HAVE_LOOPS
 363                     "loop "
 364#endif
 365#if XCHAL_HAVE_NSA
 366                     "nsa "
 367#endif
 368#if XCHAL_HAVE_MINMAX
 369                     "minmax "
 370#endif
 371#if XCHAL_HAVE_SEXT
 372                     "sext "
 373#endif
 374#if XCHAL_HAVE_CLAMPS
 375                     "clamps "
 376#endif
 377#if XCHAL_HAVE_MAC16
 378                     "mac16 "
 379#endif
 380#if XCHAL_HAVE_MUL16
 381                     "mul16 "
 382#endif
 383#if XCHAL_HAVE_MUL32
 384                     "mul32 "
 385#endif
 386#if XCHAL_HAVE_MUL32_HIGH
 387                     "mul32h "
 388#endif
 389#if XCHAL_HAVE_FP
 390                     "fpu "
 391#endif
 392                     "\n");
 393
 394        /* Registers. */
 395        seq_printf(f,"physical aregs\t: %d\n"
 396                     "misc regs\t: %d\n"
 397                     "ibreak\t\t: %d\n"
 398                     "dbreak\t\t: %d\n",
 399                     XCHAL_NUM_AREGS,
 400                     XCHAL_NUM_MISC_REGS,
 401                     XCHAL_NUM_IBREAK,
 402                     XCHAL_NUM_DBREAK);
 403
 404
 405        /* Interrupt. */
 406        seq_printf(f,"num ints\t: %d\n"
 407                     "ext ints\t: %d\n"
 408                     "int levels\t: %d\n"
 409                     "timers\t\t: %d\n"
 410                     "debug level\t: %d\n",
 411                     XCHAL_NUM_INTERRUPTS,
 412                     XCHAL_NUM_EXTINTERRUPTS,
 413                     XCHAL_NUM_INTLEVELS,
 414                     XCHAL_NUM_TIMERS,
 415                     XCHAL_DEBUGLEVEL);
 416
 417        /* Cache */
 418        seq_printf(f,"icache line size: %d\n"
 419                     "icache ways\t: %d\n"
 420                     "icache size\t: %d\n"
 421                     "icache flags\t: "
 422#if XCHAL_ICACHE_LINE_LOCKABLE
 423                     "lock"
 424#endif
 425                     "\n"
 426                     "dcache line size: %d\n"
 427                     "dcache ways\t: %d\n"
 428                     "dcache size\t: %d\n"
 429                     "dcache flags\t: "
 430#if XCHAL_DCACHE_IS_WRITEBACK
 431                     "writeback"
 432#endif
 433#if XCHAL_DCACHE_LINE_LOCKABLE
 434                     "lock"
 435#endif
 436                     "\n",
 437                     XCHAL_ICACHE_LINESIZE,
 438                     XCHAL_ICACHE_WAYS,
 439                     XCHAL_ICACHE_SIZE,
 440                     XCHAL_DCACHE_LINESIZE,
 441                     XCHAL_DCACHE_WAYS,
 442                     XCHAL_DCACHE_SIZE);
 443
 444        return 0;
 445}
 446
 447/*
 448 * We show only CPU #0 info.
 449 */
 450static void *
 451c_start(struct seq_file *f, loff_t *pos)
 452{
 453        return (void *) ((*pos == 0) ? (void *)1 : NULL);
 454}
 455
 456static void *
 457c_next(struct seq_file *f, void *v, loff_t *pos)
 458{
 459        return NULL;
 460}
 461
 462static void
 463c_stop(struct seq_file *f, void *v)
 464{
 465}
 466
 467const struct seq_operations cpuinfo_op =
 468{
 469        start:  c_start,
 470        next:   c_next,
 471        stop:   c_stop,
 472        show:   c_show
 473};
 474
 475#endif /* CONFIG_PROC_FS */
 476
 477
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.