linux/arch/parisc/kernel/setup.c
<<
>>
Prefs
   1/*
   2 *    Initial setup-routines for HP 9000 based hardware.
   3 *
   4 *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
   5 *    Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
   6 *    Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
   7 *    Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
   8 *    Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
   9 *    Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
  10 *
  11 *    Initial PA-RISC Version: 04-23-1999 by Helge Deller
  12 *
  13 *    This program is free software; you can redistribute it and/or modify
  14 *    it under the terms of the GNU General Public License as published by
  15 *    the Free Software Foundation; either version 2, or (at your option)
  16 *    any later version.
  17 *
  18 *    This program is distributed in the hope that it will be useful,
  19 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 *    GNU General Public License for more details.
  22 *
  23 *    You should have received a copy of the GNU General Public License
  24 *    along with this program; if not, write to the Free Software
  25 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26 *
  27 */
  28
  29#include <linux/kernel.h>
  30#include <linux/initrd.h>
  31#include <linux/init.h>
  32#include <linux/console.h>
  33#include <linux/seq_file.h>
  34#define PCI_DEBUG
  35#include <linux/pci.h>
  36#undef PCI_DEBUG
  37#include <linux/proc_fs.h>
  38#include <linux/export.h>
  39
  40#include <asm/processor.h>
  41#include <asm/pdc.h>
  42#include <asm/led.h>
  43#include <asm/machdep.h>        /* for pa7300lc_init() proto */
  44#include <asm/pdc_chassis.h>
  45#include <asm/io.h>
  46#include <asm/setup.h>
  47#include <asm/unwind.h>
  48
  49static char __initdata command_line[COMMAND_LINE_SIZE];
  50
  51/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
  52struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
  53struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
  54struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL;
  55
  56#if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA))
  57int parisc_bus_is_phys __read_mostly = 1;       /* Assume no IOMMU is present */
  58EXPORT_SYMBOL(parisc_bus_is_phys);
  59#endif
  60
  61void __init setup_cmdline(char **cmdline_p)
  62{
  63        extern unsigned int boot_args[];
  64
  65        /* Collect stuff passed in from the boot loader */
  66
  67        /* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
  68        if (boot_args[0] < 64) {
  69                /* called from hpux boot loader */
  70                boot_command_line[0] = '\0';
  71        } else {
  72                strlcpy(boot_command_line, (char *)__va(boot_args[1]),
  73                        COMMAND_LINE_SIZE);
  74
  75#ifdef CONFIG_BLK_DEV_INITRD
  76                if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
  77                {
  78                    initrd_start = (unsigned long)__va(boot_args[2]);
  79                    initrd_end = (unsigned long)__va(boot_args[3]);
  80                }
  81#endif
  82        }
  83
  84        strcpy(command_line, boot_command_line);
  85        *cmdline_p = command_line;
  86}
  87
  88#ifdef CONFIG_PA11
  89void __init dma_ops_init(void)
  90{
  91        switch (boot_cpu_data.cpu_type) {
  92        case pcx:
  93                /*
  94                 * We've got way too many dependencies on 1.1 semantics
  95                 * to support 1.0 boxes at this point.
  96                 */
  97                panic(  "PA-RISC Linux currently only supports machines that conform to\n"
  98                        "the PA-RISC 1.1 or 2.0 architecture specification.\n");
  99
 100        case pcxs:
 101        case pcxt:
 102                hppa_dma_ops = &pcx_dma_ops;
 103                break;
 104        case pcxl2:
 105                pa7300lc_init();
 106        case pcxl: /* falls through */
 107                hppa_dma_ops = &pcxl_dma_ops;
 108                break;
 109        default:
 110                break;
 111        }
 112}
 113#endif
 114
 115extern int init_per_cpu(int cpuid);
 116extern void collect_boot_cpu_data(void);
 117
 118void __init setup_arch(char **cmdline_p)
 119{
 120#ifdef CONFIG_64BIT
 121        extern int parisc_narrow_firmware;
 122#endif
 123        unwind_init();
 124
 125        init_per_cpu(smp_processor_id());       /* Set Modes & Enable FP */
 126
 127#ifdef CONFIG_64BIT
 128        printk(KERN_INFO "The 64-bit Kernel has started...\n");
 129#else
 130        printk(KERN_INFO "The 32-bit Kernel has started...\n");
 131#endif
 132
 133        printk(KERN_INFO "Default page size is %dKB.\n", (int)(PAGE_SIZE / 1024));
 134
 135        pdc_console_init();
 136
 137#ifdef CONFIG_64BIT
 138        if(parisc_narrow_firmware) {
 139                printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
 140        }
 141#endif
 142        setup_pdc();
 143        setup_cmdline(cmdline_p);
 144        collect_boot_cpu_data();
 145        do_memory_inventory();  /* probe for physical memory */
 146        parisc_cache_init();
 147        paging_init();
 148
 149#ifdef CONFIG_CHASSIS_LCD_LED
 150        /* initialize the LCD/LED after boot_cpu_data is available ! */
 151        led_init();             /* LCD/LED initialization */
 152#endif
 153
 154#ifdef CONFIG_PA11
 155        dma_ops_init();
 156#endif
 157
 158#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
 159        conswitchp = &dummy_con;        /* we use do_take_over_console() later ! */
 160#endif
 161
 162}
 163
 164/*
 165 * Display CPU info for all CPUs.
 166 * for parisc this is in processor.c
 167 */
 168extern int show_cpuinfo (struct seq_file *m, void *v);
 169
 170static void *
 171c_start (struct seq_file *m, loff_t *pos)
 172{
 173        /* Looks like the caller will call repeatedly until we return
 174         * 0, signaling EOF perhaps.  This could be used to sequence
 175         * through CPUs for example.  Since we print all cpu info in our
 176         * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above)
 177         * we only allow for one "position".  */
 178        return ((long)*pos < 1) ? (void *)1 : NULL;
 179}
 180
 181static void *
 182c_next (struct seq_file *m, void *v, loff_t *pos)
 183{
 184        ++*pos;
 185        return c_start(m, pos);
 186}
 187
 188static void
 189c_stop (struct seq_file *m, void *v)
 190{
 191}
 192
 193const struct seq_operations cpuinfo_op = {
 194        .start  = c_start,
 195        .next   = c_next,
 196        .stop   = c_stop,
 197        .show   = show_cpuinfo
 198};
 199
 200static void __init parisc_proc_mkdir(void)
 201{
 202        /*
 203        ** Can't call proc_mkdir() until after proc_root_init() has been
 204        ** called by start_kernel(). In other words, this code can't
 205        ** live in arch/.../setup.c because start_parisc() calls
 206        ** start_kernel().
 207        */
 208        switch (boot_cpu_data.cpu_type) {
 209        case pcxl:
 210        case pcxl2:
 211                if (NULL == proc_gsc_root)
 212                {
 213                        proc_gsc_root = proc_mkdir("bus/gsc", NULL);
 214                }
 215                break;
 216        case pcxt_:
 217        case pcxu:
 218        case pcxu_:
 219        case pcxw:
 220        case pcxw_:
 221        case pcxw2:
 222                if (NULL == proc_runway_root)
 223                {
 224                        proc_runway_root = proc_mkdir("bus/runway", NULL);
 225                }
 226                break;
 227        case mako:
 228        case mako2:
 229                if (NULL == proc_mckinley_root)
 230                {
 231                        proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
 232                }
 233                break;
 234        default:
 235                /* FIXME: this was added to prevent the compiler 
 236                 * complaining about missing pcx, pcxs and pcxt
 237                 * I'm assuming they have neither gsc nor runway */
 238                break;
 239        }
 240}
 241
 242static struct resource central_bus = {
 243        .name   = "Central Bus",
 244        .start  = F_EXTEND(0xfff80000),
 245        .end    = F_EXTEND(0xfffaffff),
 246        .flags  = IORESOURCE_MEM,
 247};
 248
 249static struct resource local_broadcast = {
 250        .name   = "Local Broadcast",
 251        .start  = F_EXTEND(0xfffb0000),
 252        .end    = F_EXTEND(0xfffdffff),
 253        .flags  = IORESOURCE_MEM,
 254};
 255
 256static struct resource global_broadcast = {
 257        .name   = "Global Broadcast",
 258        .start  = F_EXTEND(0xfffe0000),
 259        .end    = F_EXTEND(0xffffffff),
 260        .flags  = IORESOURCE_MEM,
 261};
 262
 263static int __init parisc_init_resources(void)
 264{
 265        int result;
 266
 267        result = request_resource(&iomem_resource, &central_bus);
 268        if (result < 0) {
 269                printk(KERN_ERR 
 270                       "%s: failed to claim %s address space!\n", 
 271                       __FILE__, central_bus.name);
 272                return result;
 273        }
 274
 275        result = request_resource(&iomem_resource, &local_broadcast);
 276        if (result < 0) {
 277                printk(KERN_ERR 
 278                       "%s: failed to claim %saddress space!\n", 
 279                       __FILE__, local_broadcast.name);
 280                return result;
 281        }
 282
 283        result = request_resource(&iomem_resource, &global_broadcast);
 284        if (result < 0) {
 285                printk(KERN_ERR 
 286                       "%s: failed to claim %s address space!\n", 
 287                       __FILE__, global_broadcast.name);
 288                return result;
 289        }
 290
 291        return 0;
 292}
 293
 294extern void gsc_init(void);
 295extern void processor_init(void);
 296extern void ccio_init(void);
 297extern void hppb_init(void);
 298extern void dino_init(void);
 299extern void iosapic_init(void);
 300extern void lba_init(void);
 301extern void sba_init(void);
 302extern void eisa_init(void);
 303
 304static int __init parisc_init(void)
 305{
 306        u32 osid = (OS_ID_LINUX << 16);
 307
 308        parisc_proc_mkdir();
 309        parisc_init_resources();
 310        do_device_inventory();                  /* probe for hardware */
 311
 312        parisc_pdc_chassis_init();
 313        
 314        /* set up a new led state on systems shipped LED State panel */
 315        pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
 316
 317        /* tell PDC we're Linux. Nevermind failure. */
 318        pdc_stable_write(0x40, &osid, sizeof(osid));
 319        
 320        processor_init();
 321#ifdef CONFIG_SMP
 322        pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n",
 323                num_online_cpus(), num_present_cpus(),
 324#else
 325        pr_info("CPU(s): 1 x %s at %d.%06d MHz\n",
 326#endif
 327                        boot_cpu_data.cpu_name,
 328                        boot_cpu_data.cpu_hz / 1000000,
 329                        boot_cpu_data.cpu_hz % 1000000  );
 330
 331        parisc_setup_cache_timing();
 332
 333        /* These are in a non-obvious order, will fix when we have an iotree */
 334#if defined(CONFIG_IOSAPIC)
 335        iosapic_init();
 336#endif
 337#if defined(CONFIG_IOMMU_SBA)
 338        sba_init();
 339#endif
 340#if defined(CONFIG_PCI_LBA)
 341        lba_init();
 342#endif
 343
 344        /* CCIO before any potential subdevices */
 345#if defined(CONFIG_IOMMU_CCIO)
 346        ccio_init();
 347#endif
 348
 349        /*
 350         * Need to register Asp & Wax before the EISA adapters for the IRQ
 351         * regions.  EISA must come before PCI to be sure it gets IRQ region
 352         * 0.
 353         */
 354#if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX)
 355        gsc_init();
 356#endif
 357#ifdef CONFIG_EISA
 358        eisa_init();
 359#endif
 360
 361#if defined(CONFIG_HPPB)
 362        hppb_init();
 363#endif
 364
 365#if defined(CONFIG_GSC_DINO)
 366        dino_init();
 367#endif
 368
 369#ifdef CONFIG_CHASSIS_LCD_LED
 370        register_led_regions(); /* register LED port info in procfs */
 371#endif
 372
 373        return 0;
 374}
 375arch_initcall(parisc_init);
 376
 377void start_parisc(void)
 378{
 379        extern void start_kernel(void);
 380
 381        int ret, cpunum;
 382        struct pdc_coproc_cfg coproc_cfg;
 383
 384        cpunum = smp_processor_id();
 385
 386        set_firmware_width_unlocked();
 387
 388        ret = pdc_coproc_cfg_unlocked(&coproc_cfg);
 389        if (ret >= 0 && coproc_cfg.ccr_functional) {
 390                mtctl(coproc_cfg.ccr_functional, 10);
 391
 392                per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
 393                per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
 394
 395                asm volatile ("fstd     %fr0,8(%sp)");
 396        } else {
 397                panic("must have an fpu to boot linux");
 398        }
 399
 400        start_kernel();
 401        // not reached
 402}
 403