linux/arch/arm/kernel/setup.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/kernel/setup.c
   3 *
   4 *  Copyright (C) 1995-2001 Russell King
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10#include <linux/module.h>
  11#include <linux/kernel.h>
  12#include <linux/stddef.h>
  13#include <linux/ioport.h>
  14#include <linux/delay.h>
  15#include <linux/utsname.h>
  16#include <linux/initrd.h>
  17#include <linux/console.h>
  18#include <linux/bootmem.h>
  19#include <linux/seq_file.h>
  20#include <linux/screen_info.h>
  21#include <linux/init.h>
  22#include <linux/root_dev.h>
  23#include <linux/cpu.h>
  24#include <linux/interrupt.h>
  25#include <linux/smp.h>
  26#include <linux/fs.h>
  27
  28#include <asm/unified.h>
  29#include <asm/cpu.h>
  30#include <asm/cputype.h>
  31#include <asm/elf.h>
  32#include <asm/procinfo.h>
  33#include <asm/sections.h>
  34#include <asm/setup.h>
  35#include <asm/mach-types.h>
  36#include <asm/cacheflush.h>
  37#include <asm/cachetype.h>
  38#include <asm/tlbflush.h>
  39
  40#include <asm/mach/arch.h>
  41#include <asm/mach/irq.h>
  42#include <asm/mach/time.h>
  43#include <asm/traps.h>
  44#include <asm/unwind.h>
  45
  46#include "compat.h"
  47#include "atags.h"
  48#include "tcm.h"
  49
  50#ifndef MEM_SIZE
  51#define MEM_SIZE        (16*1024*1024)
  52#endif
  53
  54#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
  55char fpe_type[8];
  56
  57static int __init fpe_setup(char *line)
  58{
  59        memcpy(fpe_type, line, 8);
  60        return 1;
  61}
  62
  63__setup("fpe=", fpe_setup);
  64#endif
  65
  66extern void paging_init(struct machine_desc *desc);
  67extern void reboot_setup(char *str);
  68
  69unsigned int processor_id;
  70EXPORT_SYMBOL(processor_id);
  71unsigned int __machine_arch_type;
  72EXPORT_SYMBOL(__machine_arch_type);
  73unsigned int cacheid;
  74EXPORT_SYMBOL(cacheid);
  75
  76unsigned int __atags_pointer __initdata;
  77
  78unsigned int system_rev;
  79EXPORT_SYMBOL(system_rev);
  80
  81unsigned int system_serial_low;
  82EXPORT_SYMBOL(system_serial_low);
  83
  84unsigned int system_serial_high;
  85EXPORT_SYMBOL(system_serial_high);
  86
  87unsigned int elf_hwcap;
  88EXPORT_SYMBOL(elf_hwcap);
  89
  90
  91#ifdef MULTI_CPU
  92struct processor processor;
  93#endif
  94#ifdef MULTI_TLB
  95struct cpu_tlb_fns cpu_tlb;
  96#endif
  97#ifdef MULTI_USER
  98struct cpu_user_fns cpu_user;
  99#endif
 100#ifdef MULTI_CACHE
 101struct cpu_cache_fns cpu_cache;
 102#endif
 103#ifdef CONFIG_OUTER_CACHE
 104struct outer_cache_fns outer_cache;
 105#endif
 106
 107struct stack {
 108        u32 irq[3];
 109        u32 abt[3];
 110        u32 und[3];
 111} ____cacheline_aligned;
 112
 113static struct stack stacks[NR_CPUS];
 114
 115char elf_platform[ELF_PLATFORM_SIZE];
 116EXPORT_SYMBOL(elf_platform);
 117
 118static const char *cpu_name;
 119static const char *machine_name;
 120static char __initdata command_line[COMMAND_LINE_SIZE];
 121
 122static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 123static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
 124#define ENDIANNESS ((char)endian_test.l)
 125
 126DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
 127
 128/*
 129 * Standard memory resources
 130 */
 131static struct resource mem_res[] = {
 132        {
 133                .name = "Video RAM",
 134                .start = 0,
 135                .end = 0,
 136                .flags = IORESOURCE_MEM
 137        },
 138        {
 139                .name = "Kernel text",
 140                .start = 0,
 141                .end = 0,
 142                .flags = IORESOURCE_MEM
 143        },
 144        {
 145                .name = "Kernel data",
 146                .start = 0,
 147                .end = 0,
 148                .flags = IORESOURCE_MEM
 149        }
 150};
 151
 152#define video_ram   mem_res[0]
 153#define kernel_code mem_res[1]
 154#define kernel_data mem_res[2]
 155
 156static struct resource io_res[] = {
 157        {
 158                .name = "reserved",
 159                .start = 0x3bc,
 160                .end = 0x3be,
 161                .flags = IORESOURCE_IO | IORESOURCE_BUSY
 162        },
 163        {
 164                .name = "reserved",
 165                .start = 0x378,
 166                .end = 0x37f,
 167                .flags = IORESOURCE_IO | IORESOURCE_BUSY
 168        },
 169        {
 170                .name = "reserved",
 171                .start = 0x278,
 172                .end = 0x27f,
 173                .flags = IORESOURCE_IO | IORESOURCE_BUSY
 174        }
 175};
 176
 177#define lp0 io_res[0]
 178#define lp1 io_res[1]
 179#define lp2 io_res[2]
 180
 181static const char *proc_arch[] = {
 182        "undefined/unknown",
 183        "3",
 184        "4",
 185        "4T",
 186        "5",
 187        "5T",
 188        "5TE",
 189        "5TEJ",
 190        "6TEJ",
 191        "7",
 192        "?(11)",
 193        "?(12)",
 194        "?(13)",
 195        "?(14)",
 196        "?(15)",
 197        "?(16)",
 198        "?(17)",
 199};
 200
 201int cpu_architecture(void)
 202{
 203        int cpu_arch;
 204
 205        if ((read_cpuid_id() & 0x0008f000) == 0) {
 206                cpu_arch = CPU_ARCH_UNKNOWN;
 207        } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
 208                cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
 209        } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
 210                cpu_arch = (read_cpuid_id() >> 16) & 7;
 211                if (cpu_arch)
 212                        cpu_arch += CPU_ARCH_ARMv3;
 213        } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
 214                unsigned int mmfr0;
 215
 216                /* Revised CPUID format. Read the Memory Model Feature
 217                 * Register 0 and check for VMSAv7 or PMSAv7 */
 218                asm("mrc        p15, 0, %0, c0, c1, 4"
 219                    : "=r" (mmfr0));
 220                if ((mmfr0 & 0x0000000f) == 0x00000003 ||
 221                    (mmfr0 & 0x000000f0) == 0x00000030)
 222                        cpu_arch = CPU_ARCH_ARMv7;
 223                else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
 224                         (mmfr0 & 0x000000f0) == 0x00000020)
 225                        cpu_arch = CPU_ARCH_ARMv6;
 226                else
 227                        cpu_arch = CPU_ARCH_UNKNOWN;
 228        } else
 229                cpu_arch = CPU_ARCH_UNKNOWN;
 230
 231        return cpu_arch;
 232}
 233
 234static void __init cacheid_init(void)
 235{
 236        unsigned int cachetype = read_cpuid_cachetype();
 237        unsigned int arch = cpu_architecture();
 238
 239        if (arch >= CPU_ARCH_ARMv6) {
 240                if ((cachetype & (7 << 29)) == 4 << 29) {
 241                        /* ARMv7 register format */
 242                        cacheid = CACHEID_VIPT_NONALIASING;
 243                        if ((cachetype & (3 << 14)) == 1 << 14)
 244                                cacheid |= CACHEID_ASID_TAGGED;
 245                } else if (cachetype & (1 << 23))
 246                        cacheid = CACHEID_VIPT_ALIASING;
 247                else
 248                        cacheid = CACHEID_VIPT_NONALIASING;
 249        } else {
 250                cacheid = CACHEID_VIVT;
 251        }
 252
 253        printk("CPU: %s data cache, %s instruction cache\n",
 254                cache_is_vivt() ? "VIVT" :
 255                cache_is_vipt_aliasing() ? "VIPT aliasing" :
 256                cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
 257                cache_is_vivt() ? "VIVT" :
 258                icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
 259                cache_is_vipt_aliasing() ? "VIPT aliasing" :
 260                cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
 261}
 262
 263/*
 264 * These functions re-use the assembly code in head.S, which
 265 * already provide the required functionality.
 266 */
 267extern struct proc_info_list *lookup_processor_type(unsigned int);
 268extern struct machine_desc *lookup_machine_type(unsigned int);
 269
 270static void __init setup_processor(void)
 271{
 272        struct proc_info_list *list;
 273
 274        /*
 275         * locate processor in the list of supported processor
 276         * types.  The linker builds this table for us from the
 277         * entries in arch/arm/mm/proc-*.S
 278         */
 279        list = lookup_processor_type(read_cpuid_id());
 280        if (!list) {
 281                printk("CPU configuration botched (ID %08x), unable "
 282                       "to continue.\n", read_cpuid_id());
 283                while (1);
 284        }
 285
 286        cpu_name = list->cpu_name;
 287
 288#ifdef MULTI_CPU
 289        processor = *list->proc;
 290#endif
 291#ifdef MULTI_TLB
 292        cpu_tlb = *list->tlb;
 293#endif
 294#ifdef MULTI_USER
 295        cpu_user = *list->user;
 296#endif
 297#ifdef MULTI_CACHE
 298        cpu_cache = *list->cache;
 299#endif
 300
 301        printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
 302               cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
 303               proc_arch[cpu_architecture()], cr_alignment);
 304
 305        sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
 306        sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
 307        elf_hwcap = list->elf_hwcap;
 308#ifndef CONFIG_ARM_THUMB
 309        elf_hwcap &= ~HWCAP_THUMB;
 310#endif
 311
 312        cacheid_init();
 313        cpu_proc_init();
 314}
 315
 316/*
 317 * cpu_init - initialise one CPU.
 318 *
 319 * cpu_init sets up the per-CPU stacks.
 320 */
 321void cpu_init(void)
 322{
 323        unsigned int cpu = smp_processor_id();
 324        struct stack *stk = &stacks[cpu];
 325
 326        if (cpu >= NR_CPUS) {
 327                printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
 328                BUG();
 329        }
 330
 331        /*
 332         * Define the placement constraint for the inline asm directive below.
 333         * In Thumb-2, msr with an immediate value is not allowed.
 334         */
 335#ifdef CONFIG_THUMB2_KERNEL
 336#define PLC     "r"
 337#else
 338#define PLC     "I"
 339#endif
 340
 341        /*
 342         * setup stacks for re-entrant exception handlers
 343         */
 344        __asm__ (
 345        "msr    cpsr_c, %1\n\t"
 346        "add    r14, %0, %2\n\t"
 347        "mov    sp, r14\n\t"
 348        "msr    cpsr_c, %3\n\t"
 349        "add    r14, %0, %4\n\t"
 350        "mov    sp, r14\n\t"
 351        "msr    cpsr_c, %5\n\t"
 352        "add    r14, %0, %6\n\t"
 353        "mov    sp, r14\n\t"
 354        "msr    cpsr_c, %7"
 355            :
 356            : "r" (stk),
 357              PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
 358              "I" (offsetof(struct stack, irq[0])),
 359              PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
 360              "I" (offsetof(struct stack, abt[0])),
 361              PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
 362              "I" (offsetof(struct stack, und[0])),
 363              PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
 364            : "r14");
 365}
 366
 367static struct machine_desc * __init setup_machine(unsigned int nr)
 368{
 369        struct machine_desc *list;
 370
 371        /*
 372         * locate machine in the list of supported machines.
 373         */
 374        list = lookup_machine_type(nr);
 375        if (!list) {
 376                printk("Machine configuration botched (nr %d), unable "
 377                       "to continue.\n", nr);
 378                while (1);
 379        }
 380
 381        printk("Machine: %s\n", list->name);
 382
 383        return list;
 384}
 385
 386static int __init arm_add_memory(unsigned long start, unsigned long size)
 387{
 388        struct membank *bank = &meminfo.bank[meminfo.nr_banks];
 389
 390        if (meminfo.nr_banks >= NR_BANKS) {
 391                printk(KERN_CRIT "NR_BANKS too low, "
 392                        "ignoring memory at %#lx\n", start);
 393                return -EINVAL;
 394        }
 395
 396        /*
 397         * Ensure that start/size are aligned to a page boundary.
 398         * Size is appropriately rounded down, start is rounded up.
 399         */
 400        size -= start & ~PAGE_MASK;
 401        bank->start = PAGE_ALIGN(start);
 402        bank->size  = size & PAGE_MASK;
 403        bank->node  = PHYS_TO_NID(start);
 404
 405        /*
 406         * Check whether this memory region has non-zero size or
 407         * invalid node number.
 408         */
 409        if (bank->size == 0 || bank->node >= MAX_NUMNODES)
 410                return -EINVAL;
 411
 412        meminfo.nr_banks++;
 413        return 0;
 414}
 415
 416/*
 417 * Pick out the memory size.  We look for mem=size@start,
 418 * where start and size are "size[KkMm]"
 419 */
 420static void __init early_mem(char **p)
 421{
 422        static int usermem __initdata = 0;
 423        unsigned long size, start;
 424
 425        /*
 426         * If the user specifies memory size, we
 427         * blow away any automatically generated
 428         * size.
 429         */
 430        if (usermem == 0) {
 431                usermem = 1;
 432                meminfo.nr_banks = 0;
 433        }
 434
 435        start = PHYS_OFFSET;
 436        size  = memparse(*p, p);
 437        if (**p == '@')
 438                start = memparse(*p + 1, p);
 439
 440        arm_add_memory(start, size);
 441}
 442__early_param("mem=", early_mem);
 443
 444/*
 445 * Initial parsing of the command line.
 446 */
 447static void __init parse_cmdline(char **cmdline_p, char *from)
 448{
 449        char c = ' ', *to = command_line;
 450        int len = 0;
 451
 452        for (;;) {
 453                if (c == ' ') {
 454                        extern struct early_params __early_begin, __early_end;
 455                        struct early_params *p;
 456
 457                        for (p = &__early_begin; p < &__early_end; p++) {
 458                                int arglen = strlen(p->arg);
 459
 460                                if (memcmp(from, p->arg, arglen) == 0) {
 461                                        if (to != command_line)
 462                                                to -= 1;
 463                                        from += arglen;
 464                                        p->fn(&from);
 465
 466                                        while (*from != ' ' && *from != '\0')
 467                                                from++;
 468                                        break;
 469                                }
 470                        }
 471                }
 472                c = *from++;
 473                if (!c)
 474                        break;
 475                if (COMMAND_LINE_SIZE <= ++len)
 476                        break;
 477                *to++ = c;
 478        }
 479        *to = '\0';
 480        *cmdline_p = command_line;
 481}
 482
 483static void __init
 484setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
 485{
 486#ifdef CONFIG_BLK_DEV_RAM
 487        extern int rd_size, rd_image_start, rd_prompt, rd_doload;
 488
 489        rd_image_start = image_start;
 490        rd_prompt = prompt;
 491        rd_doload = doload;
 492
 493        if (rd_sz)
 494                rd_size = rd_sz;
 495#endif
 496}
 497
 498static void __init
 499request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
 500{
 501        struct resource *res;
 502        int i;
 503
 504        kernel_code.start   = virt_to_phys(_text);
 505        kernel_code.end     = virt_to_phys(_etext - 1);
 506        kernel_data.start   = virt_to_phys(_data);
 507        kernel_data.end     = virt_to_phys(_end - 1);
 508
 509        for (i = 0; i < mi->nr_banks; i++) {
 510                if (mi->bank[i].size == 0)
 511                        continue;
 512
 513                res = alloc_bootmem_low(sizeof(*res));
 514                res->name  = "System RAM";
 515                res->start = mi->bank[i].start;
 516                res->end   = mi->bank[i].start + mi->bank[i].size - 1;
 517                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 518
 519                request_resource(&iomem_resource, res);
 520
 521                if (kernel_code.start >= res->start &&
 522                    kernel_code.end <= res->end)
 523                        request_resource(res, &kernel_code);
 524                if (kernel_data.start >= res->start &&
 525                    kernel_data.end <= res->end)
 526                        request_resource(res, &kernel_data);
 527        }
 528
 529        if (mdesc->video_start) {
 530                video_ram.start = mdesc->video_start;
 531                video_ram.end   = mdesc->video_end;
 532                request_resource(&iomem_resource, &video_ram);
 533        }
 534
 535        /*
 536         * Some machines don't have the possibility of ever
 537         * possessing lp0, lp1 or lp2
 538         */
 539        if (mdesc->reserve_lp0)
 540                request_resource(&ioport_resource, &lp0);
 541        if (mdesc->reserve_lp1)
 542                request_resource(&ioport_resource, &lp1);
 543        if (mdesc->reserve_lp2)
 544                request_resource(&ioport_resource, &lp2);
 545}
 546
 547/*
 548 *  Tag parsing.
 549 *
 550 * This is the new way of passing data to the kernel at boot time.  Rather
 551 * than passing a fixed inflexible structure to the kernel, we pass a list
 552 * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
 553 * tag for the list to be recognised (to distinguish the tagged list from
 554 * a param_struct).  The list is terminated with a zero-length tag (this tag
 555 * is not parsed in any way).
 556 */
 557static int __init parse_tag_core(const struct tag *tag)
 558{
 559        if (tag->hdr.size > 2) {
 560                if ((tag->u.core.flags & 1) == 0)
 561                        root_mountflags &= ~MS_RDONLY;
 562                ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
 563        }
 564        return 0;
 565}
 566
 567__tagtable(ATAG_CORE, parse_tag_core);
 568
 569static int __init parse_tag_mem32(const struct tag *tag)
 570{
 571        return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
 572}
 573
 574__tagtable(ATAG_MEM, parse_tag_mem32);
 575
 576#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 577struct screen_info screen_info = {
 578 .orig_video_lines      = 30,
 579 .orig_video_cols       = 80,
 580 .orig_video_mode       = 0,
 581 .orig_video_ega_bx     = 0,
 582 .orig_video_isVGA      = 1,
 583 .orig_video_points     = 8
 584};
 585
 586static int __init parse_tag_videotext(const struct tag *tag)
 587{
 588        screen_info.orig_x            = tag->u.videotext.x;
 589        screen_info.orig_y            = tag->u.videotext.y;
 590        screen_info.orig_video_page   = tag->u.videotext.video_page;
 591        screen_info.orig_video_mode   = tag->u.videotext.video_mode;
 592        screen_info.orig_video_cols   = tag->u.videotext.video_cols;
 593        screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
 594        screen_info.orig_video_lines  = tag->u.videotext.video_lines;
 595        screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
 596        screen_info.orig_video_points = tag->u.videotext.video_points;
 597        return 0;
 598}
 599
 600__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
 601#endif
 602
 603static int __init parse_tag_ramdisk(const struct tag *tag)
 604{
 605        setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
 606                      (tag->u.ramdisk.flags & 2) == 0,
 607                      tag->u.ramdisk.start, tag->u.ramdisk.size);
 608        return 0;
 609}
 610
 611__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
 612
 613static int __init parse_tag_serialnr(const struct tag *tag)
 614{
 615        system_serial_low = tag->u.serialnr.low;
 616        system_serial_high = tag->u.serialnr.high;
 617        return 0;
 618}
 619
 620__tagtable(ATAG_SERIAL, parse_tag_serialnr);
 621
 622static int __init parse_tag_revision(const struct tag *tag)
 623{
 624        system_rev = tag->u.revision.rev;
 625        return 0;
 626}
 627
 628__tagtable(ATAG_REVISION, parse_tag_revision);
 629
 630static int __init parse_tag_cmdline(const struct tag *tag)
 631{
 632        strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
 633        return 0;
 634}
 635
 636__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
 637
 638/*
 639 * Scan the tag table for this tag, and call its parse function.
 640 * The tag table is built by the linker from all the __tagtable
 641 * declarations.
 642 */
 643static int __init parse_tag(const struct tag *tag)
 644{
 645        extern struct tagtable __tagtable_begin, __tagtable_end;
 646        struct tagtable *t;
 647
 648        for (t = &__tagtable_begin; t < &__tagtable_end; t++)
 649                if (tag->hdr.tag == t->tag) {
 650                        t->parse(tag);
 651                        break;
 652                }
 653
 654        return t < &__tagtable_end;
 655}
 656
 657/*
 658 * Parse all tags in the list, checking both the global and architecture
 659 * specific tag tables.
 660 */
 661static void __init parse_tags(const struct tag *t)
 662{
 663        for (; t->hdr.size; t = tag_next(t))
 664                if (!parse_tag(t))
 665                        printk(KERN_WARNING
 666                                "Ignoring unrecognised tag 0x%08x\n",
 667                                t->hdr.tag);
 668}
 669
 670/*
 671 * This holds our defaults.
 672 */
 673static struct init_tags {
 674        struct tag_header hdr1;
 675        struct tag_core   core;
 676        struct tag_header hdr2;
 677        struct tag_mem32  mem;
 678        struct tag_header hdr3;
 679} init_tags __initdata = {
 680        { tag_size(tag_core), ATAG_CORE },
 681        { 1, PAGE_SIZE, 0xff },
 682        { tag_size(tag_mem32), ATAG_MEM },
 683        { MEM_SIZE, PHYS_OFFSET },
 684        { 0, ATAG_NONE }
 685};
 686
 687static void (*init_machine)(void) __initdata;
 688
 689static int __init customize_machine(void)
 690{
 691        /* customizes platform devices, or adds new ones */
 692        if (init_machine)
 693                init_machine();
 694        return 0;
 695}
 696arch_initcall(customize_machine);
 697
 698void __init setup_arch(char **cmdline_p)
 699{
 700        struct tag *tags = (struct tag *)&init_tags;
 701        struct machine_desc *mdesc;
 702        char *from = default_command_line;
 703
 704        unwind_init();
 705
 706        setup_processor();
 707        mdesc = setup_machine(machine_arch_type);
 708        machine_name = mdesc->name;
 709
 710        if (mdesc->soft_reboot)
 711                reboot_setup("s");
 712
 713        if (__atags_pointer)
 714                tags = phys_to_virt(__atags_pointer);
 715        else if (mdesc->boot_params)
 716                tags = phys_to_virt(mdesc->boot_params);
 717
 718        /*
 719         * If we have the old style parameters, convert them to
 720         * a tag list.
 721         */
 722        if (tags->hdr.tag != ATAG_CORE)
 723                convert_to_tag_list(tags);
 724        if (tags->hdr.tag != ATAG_CORE)
 725                tags = (struct tag *)&init_tags;
 726
 727        if (mdesc->fixup)
 728                mdesc->fixup(mdesc, tags, &from, &meminfo);
 729
 730        if (tags->hdr.tag == ATAG_CORE) {
 731                if (meminfo.nr_banks != 0)
 732                        squash_mem_tags(tags);
 733                save_atags(tags);
 734                parse_tags(tags);
 735        }
 736
 737        init_mm.start_code = (unsigned long) _text;
 738        init_mm.end_code   = (unsigned long) _etext;
 739        init_mm.end_data   = (unsigned long) _edata;
 740        init_mm.brk        = (unsigned long) _end;
 741
 742        memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
 743        boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 744        parse_cmdline(cmdline_p, from);
 745        paging_init(mdesc);
 746        request_standard_resources(&meminfo, mdesc);
 747
 748#ifdef CONFIG_SMP
 749        smp_init_cpus();
 750#endif
 751
 752        cpu_init();
 753        tcm_init();
 754
 755        /*
 756         * Set up various architecture-specific pointers
 757         */
 758        init_arch_irq = mdesc->init_irq;
 759        system_timer = mdesc->timer;
 760        init_machine = mdesc->init_machine;
 761
 762#ifdef CONFIG_VT
 763#if defined(CONFIG_VGA_CONSOLE)
 764        conswitchp = &vga_con;
 765#elif defined(CONFIG_DUMMY_CONSOLE)
 766        conswitchp = &dummy_con;
 767#endif
 768#endif
 769        early_trap_init();
 770}
 771
 772
 773static int __init topology_init(void)
 774{
 775        int cpu;
 776
 777        for_each_possible_cpu(cpu) {
 778                struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
 779                cpuinfo->cpu.hotpluggable = 1;
 780                register_cpu(&cpuinfo->cpu, cpu);
 781        }
 782
 783        return 0;
 784}
 785
 786subsys_initcall(topology_init);
 787
 788static const char *hwcap_str[] = {
 789        "swp",
 790        "half",
 791        "thumb",
 792        "26bit",
 793        "fastmult",
 794        "fpa",
 795        "vfp",
 796        "edsp",
 797        "java",
 798        "iwmmxt",
 799        "crunch",
 800        "thumbee",
 801        "neon",
 802        "vfpv3",
 803        "vfpv3d16",
 804        NULL
 805};
 806
 807static int c_show(struct seq_file *m, void *v)
 808{
 809        int i;
 810
 811        seq_printf(m, "Processor\t: %s rev %d (%s)\n",
 812                   cpu_name, read_cpuid_id() & 15, elf_platform);
 813
 814#if defined(CONFIG_SMP)
 815        for_each_online_cpu(i) {
 816                /*
 817                 * glibc reads /proc/cpuinfo to determine the number of
 818                 * online processors, looking for lines beginning with
 819                 * "processor".  Give glibc what it expects.
 820                 */
 821                seq_printf(m, "processor\t: %d\n", i);
 822                seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
 823                           per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
 824                           (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
 825        }
 826#else /* CONFIG_SMP */
 827        seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 828                   loops_per_jiffy / (500000/HZ),
 829                   (loops_per_jiffy / (5000/HZ)) % 100);
 830#endif
 831
 832        /* dump out the processor features */
 833        seq_puts(m, "Features\t: ");
 834
 835        for (i = 0; hwcap_str[i]; i++)
 836                if (elf_hwcap & (1 << i))
 837                        seq_printf(m, "%s ", hwcap_str[i]);
 838
 839        seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
 840        seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
 841
 842        if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
 843                /* pre-ARM7 */
 844                seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
 845        } else {
 846                if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
 847                        /* ARM7 */
 848                        seq_printf(m, "CPU variant\t: 0x%02x\n",
 849                                   (read_cpuid_id() >> 16) & 127);
 850                } else {
 851                        /* post-ARM7 */
 852                        seq_printf(m, "CPU variant\t: 0x%x\n",
 853                                   (read_cpuid_id() >> 20) & 15);
 854                }
 855                seq_printf(m, "CPU part\t: 0x%03x\n",
 856                           (read_cpuid_id() >> 4) & 0xfff);
 857        }
 858        seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
 859
 860        seq_puts(m, "\n");
 861
 862        seq_printf(m, "Hardware\t: %s\n", machine_name);
 863        seq_printf(m, "Revision\t: %04x\n", system_rev);
 864        seq_printf(m, "Serial\t\t: %08x%08x\n",
 865                   system_serial_high, system_serial_low);
 866
 867        return 0;
 868}
 869
 870static void *c_start(struct seq_file *m, loff_t *pos)
 871{
 872        return *pos < 1 ? (void *)1 : NULL;
 873}
 874
 875static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 876{
 877        ++*pos;
 878        return NULL;
 879}
 880
 881static void c_stop(struct seq_file *m, void *v)
 882{
 883}
 884
 885const struct seq_operations cpuinfo_op = {
 886        .start  = c_start,
 887        .next   = c_next,
 888        .stop   = c_stop,
 889        .show   = c_show
 890};
 891
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.