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