1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/arch/alpha/kernel/setup.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 1995 Linus Torvalds
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds /* 2.3.x bootmem, 1999 Andrea Arcangeli <[email protected]> */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds /*
111da177e4SLinus Torvalds * Bootup setup stuff.
121da177e4SLinus Torvalds */
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #include <linux/sched.h>
151da177e4SLinus Torvalds #include <linux/kernel.h>
161da177e4SLinus Torvalds #include <linux/mm.h>
171da177e4SLinus Torvalds #include <linux/stddef.h>
181da177e4SLinus Torvalds #include <linux/unistd.h>
191da177e4SLinus Torvalds #include <linux/ptrace.h>
201da177e4SLinus Torvalds #include <linux/slab.h>
211da177e4SLinus Torvalds #include <linux/user.h>
22894673eeSJon Smirl #include <linux/screen_info.h>
231da177e4SLinus Torvalds #include <linux/delay.h>
241da177e4SLinus Torvalds #include <linux/mc146818rtc.h>
251da177e4SLinus Torvalds #include <linux/console.h>
26917b1f78SBrian Uhrain says #include <linux/cpu.h>
271da177e4SLinus Torvalds #include <linux/errno.h>
281da177e4SLinus Torvalds #include <linux/init.h>
291da177e4SLinus Torvalds #include <linux/string.h>
301da177e4SLinus Torvalds #include <linux/ioport.h>
31f39650deSAndy Shevchenko #include <linux/panic_notifier.h>
32e5c6c8e4SMichael Neuling #include <linux/platform_device.h>
336471f52aSMike Rapoport #include <linux/memblock.h>
341da177e4SLinus Torvalds #include <linux/pci.h>
351da177e4SLinus Torvalds #include <linux/seq_file.h>
361da177e4SLinus Torvalds #include <linux/root_dev.h>
371da177e4SLinus Torvalds #include <linux/initrd.h>
381da177e4SLinus Torvalds #include <linux/eisa.h>
3922a9835cSDave Hansen #include <linux/pfn.h>
401da177e4SLinus Torvalds #ifdef CONFIG_MAGIC_SYSRQ
411da177e4SLinus Torvalds #include <linux/sysrq.h>
421da177e4SLinus Torvalds #include <linux/reboot.h>
431da177e4SLinus Torvalds #endif
441da177e4SLinus Torvalds #include <linux/notifier.h>
451da177e4SLinus Torvalds #include <asm/setup.h>
461da177e4SLinus Torvalds #include <asm/io.h>
4774fd1b68SRichard Henderson #include <linux/log2.h>
4800cd1176SPaul Gortmaker #include <linux/export.h>
491da177e4SLinus Torvalds
501da177e4SLinus Torvalds static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
511da177e4SLinus Torvalds static struct notifier_block alpha_panic_block = {
521da177e4SLinus Torvalds alpha_panic_event,
531da177e4SLinus Torvalds NULL,
541da177e4SLinus Torvalds INT_MAX /* try to do it first */
551da177e4SLinus Torvalds };
561da177e4SLinus Torvalds
577c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
581da177e4SLinus Torvalds #include <asm/hwrpb.h>
591da177e4SLinus Torvalds #include <asm/dma.h>
601da177e4SLinus Torvalds #include <asm/mmu_context.h>
611da177e4SLinus Torvalds #include <asm/console.h>
621da177e4SLinus Torvalds
631da177e4SLinus Torvalds #include "proto.h"
641da177e4SLinus Torvalds #include "pci_impl.h"
651da177e4SLinus Torvalds
661da177e4SLinus Torvalds
671da177e4SLinus Torvalds struct hwrpb_struct *hwrpb;
68cff52dafSAl Viro EXPORT_SYMBOL(hwrpb);
691da177e4SLinus Torvalds unsigned long srm_hae;
701da177e4SLinus Torvalds
711da177e4SLinus Torvalds int alpha_l1i_cacheshape;
721da177e4SLinus Torvalds int alpha_l1d_cacheshape;
731da177e4SLinus Torvalds int alpha_l2_cacheshape;
741da177e4SLinus Torvalds int alpha_l3_cacheshape;
751da177e4SLinus Torvalds
761da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
771da177e4SLinus Torvalds /* 0=minimum, 1=verbose, 2=all */
781da177e4SLinus Torvalds /* These can be overridden via the command line, ie "verbose_mcheck=2") */
791da177e4SLinus Torvalds unsigned long alpha_verbose_mcheck = CONFIG_VERBOSE_MCHECK_ON;
801da177e4SLinus Torvalds #endif
811da177e4SLinus Torvalds
821da177e4SLinus Torvalds /* Which processor we booted from. */
831da177e4SLinus Torvalds int boot_cpuid;
841da177e4SLinus Torvalds
851da177e4SLinus Torvalds /*
861da177e4SLinus Torvalds * Using SRM callbacks for initial console output. This works from
871da177e4SLinus Torvalds * setup_arch() time through the end of time_init(), as those places
881da177e4SLinus Torvalds * are under our (Alpha) control.
891da177e4SLinus Torvalds
901da177e4SLinus Torvalds * "srmcons" specified in the boot command arguments allows us to
911da177e4SLinus Torvalds * see kernel messages during the period of time before the true
921da177e4SLinus Torvalds * console device is "registered" during console_init().
931da177e4SLinus Torvalds * As of this version (2.5.59), console_init() will call
941da177e4SLinus Torvalds * disable_early_printk() as the last action before initializing
951da177e4SLinus Torvalds * the console drivers. That's the last possible time srmcons can be
961da177e4SLinus Torvalds * unregistered without interfering with console behavior.
971da177e4SLinus Torvalds *
981da177e4SLinus Torvalds * By default, OFF; set it with a bootcommand arg of "srmcons" or
991da177e4SLinus Torvalds * "console=srm". The meaning of these two args is:
1001da177e4SLinus Torvalds * "srmcons" - early callback prints
1011da177e4SLinus Torvalds * "console=srm" - full callback based console, including early prints
1021da177e4SLinus Torvalds */
1031da177e4SLinus Torvalds int srmcons_output = 0;
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds /* Enforce a memory size limit; useful for testing. By default, none. */
1061da177e4SLinus Torvalds unsigned long mem_size_limit = 0;
1071da177e4SLinus Torvalds
1081da177e4SLinus Torvalds /* Set AGP GART window size (0 means disabled). */
1091da177e4SLinus Torvalds unsigned long alpha_agpgart_size = DEFAULT_AGP_APER_SIZE;
1101da177e4SLinus Torvalds
1111da177e4SLinus Torvalds #ifdef CONFIG_ALPHA_GENERIC
1121da177e4SLinus Torvalds struct alpha_machine_vector alpha_mv;
11300fc0e0dSAl Viro EXPORT_SYMBOL(alpha_mv);
114994dcf70SRichard Henderson #endif
115994dcf70SRichard Henderson
116994dcf70SRichard Henderson #ifndef alpha_using_srm
1171da177e4SLinus Torvalds int alpha_using_srm;
118cff52dafSAl Viro EXPORT_SYMBOL(alpha_using_srm);
1191da177e4SLinus Torvalds #endif
1201da177e4SLinus Torvalds
121994dcf70SRichard Henderson #ifndef alpha_using_qemu
122994dcf70SRichard Henderson int alpha_using_qemu;
123994dcf70SRichard Henderson #endif
124994dcf70SRichard Henderson
1251da177e4SLinus Torvalds static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long,
1261da177e4SLinus Torvalds unsigned long);
1271da177e4SLinus Torvalds static struct alpha_machine_vector *get_sysvec_byname(const char *);
1281da177e4SLinus Torvalds static void get_sysnames(unsigned long, unsigned long, unsigned long,
1291da177e4SLinus Torvalds char **, char **);
1301da177e4SLinus Torvalds static void determine_cpu_caches (unsigned int);
1311da177e4SLinus Torvalds
1323c253ca0SAlon Bar-Lev static char __initdata command_line[COMMAND_LINE_SIZE];
1331da177e4SLinus Torvalds
1348a736ddfSArnd Bergmann #ifdef CONFIG_VGA_CONSOLE
1351da177e4SLinus Torvalds /*
1361da177e4SLinus Torvalds * The format of "screen_info" is strange, and due to early
1371da177e4SLinus Torvalds * i386-setup code. This is just enough to make the console
1381da177e4SLinus Torvalds * code think we're on a VGA color display.
1391da177e4SLinus Torvalds */
1401da177e4SLinus Torvalds
141555624c0SArnd Bergmann struct screen_info vgacon_screen_info = {
1421da177e4SLinus Torvalds .orig_x = 0,
1431da177e4SLinus Torvalds .orig_y = 25,
1441da177e4SLinus Torvalds .orig_video_cols = 80,
1451da177e4SLinus Torvalds .orig_video_lines = 25,
1461da177e4SLinus Torvalds .orig_video_isVGA = 1,
1471da177e4SLinus Torvalds .orig_video_points = 16
1481da177e4SLinus Torvalds };
1498a736ddfSArnd Bergmann #endif
150cff52dafSAl Viro
1511da177e4SLinus Torvalds /*
1521da177e4SLinus Torvalds * The direct map I/O window, if any. This should be the same
1531da177e4SLinus Torvalds * for all busses, since it's used by virt_to_bus.
1541da177e4SLinus Torvalds */
1551da177e4SLinus Torvalds
1561da177e4SLinus Torvalds unsigned long __direct_map_base;
1571da177e4SLinus Torvalds unsigned long __direct_map_size;
158cff52dafSAl Viro EXPORT_SYMBOL(__direct_map_base);
159cff52dafSAl Viro EXPORT_SYMBOL(__direct_map_size);
1601da177e4SLinus Torvalds
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds * Declare all of the machine vectors.
1631da177e4SLinus Torvalds */
1641da177e4SLinus Torvalds
1651da177e4SLinus Torvalds /* GCC 2.7.2 (on alpha at least) is lame. It does not support either
1661da177e4SLinus Torvalds __attribute__((weak)) or #pragma weak. Bypass it and talk directly
1671da177e4SLinus Torvalds to the assembler. */
1681da177e4SLinus Torvalds
1691da177e4SLinus Torvalds #define WEAK(X) \
1701da177e4SLinus Torvalds extern struct alpha_machine_vector X; \
1711da177e4SLinus Torvalds asm(".weak "#X)
1721da177e4SLinus Torvalds
1731da177e4SLinus Torvalds WEAK(alcor_mv);
1741da177e4SLinus Torvalds WEAK(clipper_mv);
1751da177e4SLinus Torvalds WEAK(dp264_mv);
1761da177e4SLinus Torvalds WEAK(eb164_mv);
1771da177e4SLinus Torvalds WEAK(eiger_mv);
1781da177e4SLinus Torvalds WEAK(lx164_mv);
1791da177e4SLinus Torvalds WEAK(marvel_ev7_mv);
1801da177e4SLinus Torvalds WEAK(miata_mv);
1811da177e4SLinus Torvalds WEAK(mikasa_primo_mv);
1821da177e4SLinus Torvalds WEAK(monet_mv);
1831da177e4SLinus Torvalds WEAK(nautilus_mv);
1841da177e4SLinus Torvalds WEAK(noritake_primo_mv);
1851da177e4SLinus Torvalds WEAK(pc164_mv);
1861da177e4SLinus Torvalds WEAK(privateer_mv);
1871da177e4SLinus Torvalds WEAK(rawhide_mv);
1881da177e4SLinus Torvalds WEAK(ruffian_mv);
1891da177e4SLinus Torvalds WEAK(rx164_mv);
1901da177e4SLinus Torvalds WEAK(sable_gamma_mv);
1911da177e4SLinus Torvalds WEAK(shark_mv);
1921da177e4SLinus Torvalds WEAK(sx164_mv);
1931da177e4SLinus Torvalds WEAK(takara_mv);
1941da177e4SLinus Torvalds WEAK(titan_mv);
1951da177e4SLinus Torvalds WEAK(webbrick_mv);
1961da177e4SLinus Torvalds WEAK(wildfire_mv);
1971da177e4SLinus Torvalds WEAK(xlt_mv);
1981da177e4SLinus Torvalds
1991da177e4SLinus Torvalds #undef WEAK
2001da177e4SLinus Torvalds
2011da177e4SLinus Torvalds /*
2021da177e4SLinus Torvalds * I/O resources inherited from PeeCees. Except for perhaps the
2031da177e4SLinus Torvalds * turbochannel alphas, everyone has these on some sort of SuperIO chip.
2041da177e4SLinus Torvalds *
2051da177e4SLinus Torvalds * ??? If this becomes less standard, move the struct out into the
2061da177e4SLinus Torvalds * machine vector.
2071da177e4SLinus Torvalds */
2081da177e4SLinus Torvalds
2091da177e4SLinus Torvalds static void __init
reserve_std_resources(void)2101da177e4SLinus Torvalds reserve_std_resources(void)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds static struct resource standard_io_resources[] = {
213f81f335aSArnd Bergmann { .name = "rtc", .start = 0x70, .end = 0x7f},
2141da177e4SLinus Torvalds { .name = "dma1", .start = 0x00, .end = 0x1f },
2151da177e4SLinus Torvalds { .name = "pic1", .start = 0x20, .end = 0x3f },
2161da177e4SLinus Torvalds { .name = "timer", .start = 0x40, .end = 0x5f },
2171da177e4SLinus Torvalds { .name = "keyboard", .start = 0x60, .end = 0x6f },
2181da177e4SLinus Torvalds { .name = "dma page reg", .start = 0x80, .end = 0x8f },
2191da177e4SLinus Torvalds { .name = "pic2", .start = 0xa0, .end = 0xbf },
2201da177e4SLinus Torvalds { .name = "dma2", .start = 0xc0, .end = 0xdf },
2211da177e4SLinus Torvalds };
2221da177e4SLinus Torvalds
2231da177e4SLinus Torvalds struct resource *io = &ioport_resource;
2241da177e4SLinus Torvalds size_t i;
2251da177e4SLinus Torvalds
2261da177e4SLinus Torvalds if (hose_head) {
2271da177e4SLinus Torvalds struct pci_controller *hose;
2281da177e4SLinus Torvalds for (hose = hose_head; hose; hose = hose->next)
2291da177e4SLinus Torvalds if (hose->index == 0) {
2301da177e4SLinus Torvalds io = hose->io_space;
2311da177e4SLinus Torvalds break;
2321da177e4SLinus Torvalds }
2331da177e4SLinus Torvalds }
2341da177e4SLinus Torvalds
23525c8716cSTobias Klauser for (i = 0; i < ARRAY_SIZE(standard_io_resources); ++i)
2361da177e4SLinus Torvalds request_resource(io, standard_io_resources+i);
2371da177e4SLinus Torvalds }
2381da177e4SLinus Torvalds
2391da177e4SLinus Torvalds #define PFN_MAX PFN_DOWN(0x80000000)
240fb26b3e6SRoel Kluin #define for_each_mem_cluster(memdesc, _cluster, i) \
241fb26b3e6SRoel Kluin for ((_cluster) = (memdesc)->cluster, (i) = 0; \
242fb26b3e6SRoel Kluin (i) < (memdesc)->numclusters; (i)++, (_cluster)++)
2431da177e4SLinus Torvalds
2441da177e4SLinus Torvalds static unsigned long __init
get_mem_size_limit(char * s)2451da177e4SLinus Torvalds get_mem_size_limit(char *s)
2461da177e4SLinus Torvalds {
2471da177e4SLinus Torvalds unsigned long end = 0;
2481da177e4SLinus Torvalds char *from = s;
2491da177e4SLinus Torvalds
2501da177e4SLinus Torvalds end = simple_strtoul(from, &from, 0);
2511da177e4SLinus Torvalds if ( *from == 'K' || *from == 'k' ) {
2521da177e4SLinus Torvalds end = end << 10;
2531da177e4SLinus Torvalds from++;
2541da177e4SLinus Torvalds } else if ( *from == 'M' || *from == 'm' ) {
2551da177e4SLinus Torvalds end = end << 20;
2561da177e4SLinus Torvalds from++;
2571da177e4SLinus Torvalds } else if ( *from == 'G' || *from == 'g' ) {
2581da177e4SLinus Torvalds end = end << 30;
2591da177e4SLinus Torvalds from++;
2601da177e4SLinus Torvalds }
2611da177e4SLinus Torvalds return end >> PAGE_SHIFT; /* Return the PFN of the limit. */
2621da177e4SLinus Torvalds }
2631da177e4SLinus Torvalds
2641da177e4SLinus Torvalds #ifdef CONFIG_BLK_DEV_INITRD
2651da177e4SLinus Torvalds void * __init
move_initrd(unsigned long mem_limit)2661da177e4SLinus Torvalds move_initrd(unsigned long mem_limit)
2671da177e4SLinus Torvalds {
2681da177e4SLinus Torvalds void *start;
2691da177e4SLinus Torvalds unsigned long size;
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds size = initrd_end - initrd_start;
2729415673eSMike Rapoport start = memblock_alloc(PAGE_ALIGN(size), PAGE_SIZE);
2731da177e4SLinus Torvalds if (!start || __pa(start) + size > mem_limit) {
2741da177e4SLinus Torvalds initrd_start = initrd_end = 0;
2751da177e4SLinus Torvalds return NULL;
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds memmove(start, (void *)initrd_start, size);
2781da177e4SLinus Torvalds initrd_start = (unsigned long)start;
2791da177e4SLinus Torvalds initrd_end = initrd_start + size;
2801da177e4SLinus Torvalds printk("initrd moved to %p\n", start);
2811da177e4SLinus Torvalds return start;
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds #endif
2841da177e4SLinus Torvalds
2851da177e4SLinus Torvalds static void __init
setup_memory(void * kernel_end)2861da177e4SLinus Torvalds setup_memory(void *kernel_end)
2871da177e4SLinus Torvalds {
2881da177e4SLinus Torvalds struct memclust_struct * cluster;
2891da177e4SLinus Torvalds struct memdesc_struct * memdesc;
2906471f52aSMike Rapoport unsigned long kernel_size;
2911da177e4SLinus Torvalds unsigned long i;
2921da177e4SLinus Torvalds
2931da177e4SLinus Torvalds /* Find free clusters, and init and free the bootmem accordingly. */
2941da177e4SLinus Torvalds memdesc = (struct memdesc_struct *)
2951da177e4SLinus Torvalds (hwrpb->mddt_offset + (unsigned long) hwrpb);
2961da177e4SLinus Torvalds
2971da177e4SLinus Torvalds for_each_mem_cluster(memdesc, cluster, i) {
2986471f52aSMike Rapoport unsigned long end;
2996471f52aSMike Rapoport
3001da177e4SLinus Torvalds printk("memcluster %lu, usage %01lx, start %8lu, end %8lu\n",
3011da177e4SLinus Torvalds i, cluster->usage, cluster->start_pfn,
3021da177e4SLinus Torvalds cluster->start_pfn + cluster->numpages);
3031da177e4SLinus Torvalds
3041da177e4SLinus Torvalds end = cluster->start_pfn + cluster->numpages;
3051da177e4SLinus Torvalds if (end > max_low_pfn)
3061da177e4SLinus Torvalds max_low_pfn = end;
3076471f52aSMike Rapoport
3086471f52aSMike Rapoport memblock_add(PFN_PHYS(cluster->start_pfn),
3096471f52aSMike Rapoport cluster->numpages << PAGE_SHIFT);
310640b7ea5SMike Rapoport
311640b7ea5SMike Rapoport /* Bit 0 is console/PALcode reserved. Bit 1 is
312640b7ea5SMike Rapoport non-volatile memory -- we might want to mark
313640b7ea5SMike Rapoport this for later. */
314640b7ea5SMike Rapoport if (cluster->usage & 3)
315640b7ea5SMike Rapoport memblock_reserve(PFN_PHYS(cluster->start_pfn),
316640b7ea5SMike Rapoport cluster->numpages << PAGE_SHIFT);
3171da177e4SLinus Torvalds }
3181da177e4SLinus Torvalds
3191da177e4SLinus Torvalds /*
3201da177e4SLinus Torvalds * Except for the NUMA systems (wildfire, marvel) all of the
3211da177e4SLinus Torvalds * Alpha systems we run on support 32GB of memory or less.
3221da177e4SLinus Torvalds * Since the NUMA systems introduce large holes in memory addressing,
3231da177e4SLinus Torvalds * we can get into a situation where there is not enough contiguous
3241da177e4SLinus Torvalds * memory for the memory map.
3251da177e4SLinus Torvalds *
3261da177e4SLinus Torvalds * Limit memory to the first 32GB to limit the NUMA systems to
3271da177e4SLinus Torvalds * memory on their first node (wildfire) or 2 (marvel) to avoid
3281da177e4SLinus Torvalds * not being able to produce the memory map. In order to access
3291da177e4SLinus Torvalds * all of the memory on the NUMA systems, build with discontiguous
3301da177e4SLinus Torvalds * memory support.
3311da177e4SLinus Torvalds *
3321da177e4SLinus Torvalds * If the user specified a memory limit, let that memory limit stand.
3331da177e4SLinus Torvalds */
3341da177e4SLinus Torvalds if (!mem_size_limit)
3351da177e4SLinus Torvalds mem_size_limit = (32ul * 1024 * 1024 * 1024) >> PAGE_SHIFT;
3361da177e4SLinus Torvalds
3371da177e4SLinus Torvalds if (mem_size_limit && max_low_pfn >= mem_size_limit)
3381da177e4SLinus Torvalds {
3391da177e4SLinus Torvalds printk("setup: forcing memory size to %ldK (from %ldK).\n",
3401da177e4SLinus Torvalds mem_size_limit << (PAGE_SHIFT - 10),
3411da177e4SLinus Torvalds max_low_pfn << (PAGE_SHIFT - 10));
3421da177e4SLinus Torvalds max_low_pfn = mem_size_limit;
3431da177e4SLinus Torvalds }
3441da177e4SLinus Torvalds
3456471f52aSMike Rapoport /* Reserve the kernel memory. */
3466471f52aSMike Rapoport kernel_size = virt_to_phys(kernel_end) - KERNEL_START_PHYS;
3476471f52aSMike Rapoport memblock_reserve(KERNEL_START_PHYS, kernel_size);
3481da177e4SLinus Torvalds
3491da177e4SLinus Torvalds #ifdef CONFIG_BLK_DEV_INITRD
3501da177e4SLinus Torvalds initrd_start = INITRD_START;
3511da177e4SLinus Torvalds if (initrd_start) {
3521da177e4SLinus Torvalds initrd_end = initrd_start+INITRD_SIZE;
3531da177e4SLinus Torvalds printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
3541da177e4SLinus Torvalds (void *) initrd_start, INITRD_SIZE);
3551da177e4SLinus Torvalds
3561da177e4SLinus Torvalds if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
3571da177e4SLinus Torvalds if (!move_initrd(PFN_PHYS(max_low_pfn)))
3581da177e4SLinus Torvalds printk("initrd extends beyond end of memory "
3591da177e4SLinus Torvalds "(0x%08lx > 0x%p)\ndisabling initrd\n",
3601da177e4SLinus Torvalds initrd_end,
3611da177e4SLinus Torvalds phys_to_virt(PFN_PHYS(max_low_pfn)));
3621da177e4SLinus Torvalds } else {
3636471f52aSMike Rapoport memblock_reserve(virt_to_phys((void *)initrd_start),
3646471f52aSMike Rapoport INITRD_SIZE);
3651da177e4SLinus Torvalds }
3661da177e4SLinus Torvalds }
3671da177e4SLinus Torvalds #endif /* CONFIG_BLK_DEV_INITRD */
3681da177e4SLinus Torvalds }
3691da177e4SLinus Torvalds
page_is_ram(unsigned long pfn)3706ccbd7fdSMasahiro Yamada int page_is_ram(unsigned long pfn)
3711da177e4SLinus Torvalds {
3721da177e4SLinus Torvalds struct memclust_struct * cluster;
3731da177e4SLinus Torvalds struct memdesc_struct * memdesc;
3741da177e4SLinus Torvalds unsigned long i;
3751da177e4SLinus Torvalds
3761da177e4SLinus Torvalds memdesc = (struct memdesc_struct *)
3771da177e4SLinus Torvalds (hwrpb->mddt_offset + (unsigned long) hwrpb);
3781da177e4SLinus Torvalds for_each_mem_cluster(memdesc, cluster, i)
3791da177e4SLinus Torvalds {
3801da177e4SLinus Torvalds if (pfn >= cluster->start_pfn &&
3811da177e4SLinus Torvalds pfn < cluster->start_pfn + cluster->numpages) {
3821da177e4SLinus Torvalds return (cluster->usage & 3) ? 0 : 1;
3831da177e4SLinus Torvalds }
3841da177e4SLinus Torvalds }
3851da177e4SLinus Torvalds
3861da177e4SLinus Torvalds return 0;
3871da177e4SLinus Torvalds }
3881da177e4SLinus Torvalds
389917b1f78SBrian Uhrain says static int __init
register_cpus(void)390917b1f78SBrian Uhrain says register_cpus(void)
391917b1f78SBrian Uhrain says {
392917b1f78SBrian Uhrain says int i;
393917b1f78SBrian Uhrain says
394917b1f78SBrian Uhrain says for_each_possible_cpu(i) {
395917b1f78SBrian Uhrain says struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
396917b1f78SBrian Uhrain says if (!p)
397917b1f78SBrian Uhrain says return -ENOMEM;
39876b67ed9SKAMEZAWA Hiroyuki register_cpu(p, i);
399917b1f78SBrian Uhrain says }
400917b1f78SBrian Uhrain says return 0;
401917b1f78SBrian Uhrain says }
402917b1f78SBrian Uhrain says
403917b1f78SBrian Uhrain says arch_initcall(register_cpus);
404917b1f78SBrian Uhrain says
4050f1c9688SEmil Velikov #ifdef CONFIG_MAGIC_SYSRQ
sysrq_reboot_handler(u8 unused)406bcb48185SJiri Slaby static void sysrq_reboot_handler(u8 unused)
407777747f6SJoerg Roedel {
408777747f6SJoerg Roedel machine_halt();
409777747f6SJoerg Roedel }
410777747f6SJoerg Roedel
411f95850ecSEmil Velikov static const struct sysrq_key_op srm_sysrq_reboot_op = {
412777747f6SJoerg Roedel .handler = sysrq_reboot_handler,
4130f1c9688SEmil Velikov .help_msg = "reboot(b)",
4140f1c9688SEmil Velikov .action_msg = "Resetting",
4150f1c9688SEmil Velikov .enable_mask = SYSRQ_ENABLE_BOOT,
4160f1c9688SEmil Velikov };
4170f1c9688SEmil Velikov #endif
4180f1c9688SEmil Velikov
4191da177e4SLinus Torvalds void __init
setup_arch(char ** cmdline_p)4201da177e4SLinus Torvalds setup_arch(char **cmdline_p)
4211da177e4SLinus Torvalds {
4221da177e4SLinus Torvalds extern char _end[];
4231da177e4SLinus Torvalds
4241da177e4SLinus Torvalds struct alpha_machine_vector *vec = NULL;
4251da177e4SLinus Torvalds struct percpu_struct *cpu;
4261da177e4SLinus Torvalds char *type_name, *var_name, *p;
4271da177e4SLinus Torvalds void *kernel_end = _end; /* end of kernel */
4281da177e4SLinus Torvalds char *args = command_line;
4291da177e4SLinus Torvalds
4301da177e4SLinus Torvalds hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
4311da177e4SLinus Torvalds boot_cpuid = hard_smp_processor_id();
4321da177e4SLinus Torvalds
4331da177e4SLinus Torvalds /*
4341da177e4SLinus Torvalds * Pre-process the system type to make sure it will be valid.
4351da177e4SLinus Torvalds *
4361da177e4SLinus Torvalds * This may restore real CABRIO and EB66+ family names, ie
4371da177e4SLinus Torvalds * EB64+ and EB66.
4381da177e4SLinus Torvalds *
4391da177e4SLinus Torvalds * Oh, and "white box" AS800 (aka DIGITAL Server 3000 series)
4401da177e4SLinus Torvalds * and AS1200 (DIGITAL Server 5000 series) have the type as
4411da177e4SLinus Torvalds * the negative of the real one.
4421da177e4SLinus Torvalds */
4431da177e4SLinus Torvalds if ((long)hwrpb->sys_type < 0) {
4441da177e4SLinus Torvalds hwrpb->sys_type = -((long)hwrpb->sys_type);
4451da177e4SLinus Torvalds hwrpb_update_checksum(hwrpb);
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds
4481da177e4SLinus Torvalds /* Register a call for panic conditions. */
449e041c683SAlan Stern atomic_notifier_chain_register(&panic_notifier_list,
450e041c683SAlan Stern &alpha_panic_block);
4511da177e4SLinus Torvalds
452994dcf70SRichard Henderson #ifndef alpha_using_srm
4531da177e4SLinus Torvalds /* Assume that we've booted from SRM if we haven't booted from MILO.
4541da177e4SLinus Torvalds Detect the later by looking for "MILO" in the system serial nr. */
4555f14596eSChuhong Yuan alpha_using_srm = !str_has_prefix((const char *)hwrpb->ssn, "MILO");
4561da177e4SLinus Torvalds #endif
457994dcf70SRichard Henderson #ifndef alpha_using_qemu
458994dcf70SRichard Henderson /* Similarly, look for QEMU. */
459994dcf70SRichard Henderson alpha_using_qemu = strstr((const char *)hwrpb->ssn, "QEMU") != 0;
460994dcf70SRichard Henderson #endif
4611da177e4SLinus Torvalds
4621da177e4SLinus Torvalds /* If we are using SRM, we want to allow callbacks
4631da177e4SLinus Torvalds as early as possible, so do this NOW, and then
4641da177e4SLinus Torvalds they should work immediately thereafter.
4651da177e4SLinus Torvalds */
4661da177e4SLinus Torvalds kernel_end = callback_init(kernel_end);
4671da177e4SLinus Torvalds
4681da177e4SLinus Torvalds /*
4691da177e4SLinus Torvalds * Locate the command line.
4701da177e4SLinus Torvalds */
47188040e67SWolfram Sang strscpy(command_line, COMMAND_LINE, sizeof(command_line));
4723c253ca0SAlon Bar-Lev strcpy(boot_command_line, command_line);
4731da177e4SLinus Torvalds *cmdline_p = command_line;
4741da177e4SLinus Torvalds
4751da177e4SLinus Torvalds /*
4761da177e4SLinus Torvalds * Process command-line arguments.
4771da177e4SLinus Torvalds */
4781da177e4SLinus Torvalds while ((p = strsep(&args, " \t")) != NULL) {
4791da177e4SLinus Torvalds if (!*p) continue;
4801da177e4SLinus Torvalds if (strncmp(p, "alpha_mv=", 9) == 0) {
4811da177e4SLinus Torvalds vec = get_sysvec_byname(p+9);
4821da177e4SLinus Torvalds continue;
4831da177e4SLinus Torvalds }
4841da177e4SLinus Torvalds if (strncmp(p, "cycle=", 6) == 0) {
4851da177e4SLinus Torvalds est_cycle_freq = simple_strtol(p+6, NULL, 0);
4861da177e4SLinus Torvalds continue;
4871da177e4SLinus Torvalds }
4881da177e4SLinus Torvalds if (strncmp(p, "mem=", 4) == 0) {
4891da177e4SLinus Torvalds mem_size_limit = get_mem_size_limit(p+4);
4901da177e4SLinus Torvalds continue;
4911da177e4SLinus Torvalds }
4921da177e4SLinus Torvalds if (strncmp(p, "srmcons", 7) == 0) {
4931da177e4SLinus Torvalds srmcons_output |= 1;
4941da177e4SLinus Torvalds continue;
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds if (strncmp(p, "console=srm", 11) == 0) {
4971da177e4SLinus Torvalds srmcons_output |= 2;
4981da177e4SLinus Torvalds continue;
4991da177e4SLinus Torvalds }
5001da177e4SLinus Torvalds if (strncmp(p, "gartsize=", 9) == 0) {
5011da177e4SLinus Torvalds alpha_agpgart_size =
5021da177e4SLinus Torvalds get_mem_size_limit(p+9) << PAGE_SHIFT;
5031da177e4SLinus Torvalds continue;
5041da177e4SLinus Torvalds }
5051da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
5061da177e4SLinus Torvalds if (strncmp(p, "verbose_mcheck=", 15) == 0) {
5071da177e4SLinus Torvalds alpha_verbose_mcheck = simple_strtol(p+15, NULL, 0);
5081da177e4SLinus Torvalds continue;
5091da177e4SLinus Torvalds }
5101da177e4SLinus Torvalds #endif
5111da177e4SLinus Torvalds }
5121da177e4SLinus Torvalds
5131da177e4SLinus Torvalds /* Replace the command line, now that we've killed it with strsep. */
5143c253ca0SAlon Bar-Lev strcpy(command_line, boot_command_line);
5151da177e4SLinus Torvalds
5161da177e4SLinus Torvalds /* If we want SRM console printk echoing early, do it now. */
5171da177e4SLinus Torvalds if (alpha_using_srm && srmcons_output) {
5181da177e4SLinus Torvalds register_srm_console();
5191da177e4SLinus Torvalds
5201da177e4SLinus Torvalds /*
5211da177e4SLinus Torvalds * If "console=srm" was specified, clear the srmcons_output
5221da177e4SLinus Torvalds * flag now so that time.c won't unregister_srm_console
5231da177e4SLinus Torvalds */
5241da177e4SLinus Torvalds if (srmcons_output & 2)
5251da177e4SLinus Torvalds srmcons_output = 0;
5261da177e4SLinus Torvalds }
5271da177e4SLinus Torvalds
5281da177e4SLinus Torvalds #ifdef CONFIG_MAGIC_SYSRQ
5291da177e4SLinus Torvalds /* If we're using SRM, make sysrq-b halt back to the prom,
5301da177e4SLinus Torvalds not auto-reboot. */
5311da177e4SLinus Torvalds if (alpha_using_srm) {
5320f1c9688SEmil Velikov unregister_sysrq_key('b', __sysrq_reboot_op);
5330f1c9688SEmil Velikov register_sysrq_key('b', &srm_sysrq_reboot_op);
5341da177e4SLinus Torvalds }
5351da177e4SLinus Torvalds #endif
5361da177e4SLinus Torvalds
5371da177e4SLinus Torvalds /*
5381da177e4SLinus Torvalds * Identify and reconfigure for the current system.
5391da177e4SLinus Torvalds */
5401da177e4SLinus Torvalds cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
5411da177e4SLinus Torvalds
5421da177e4SLinus Torvalds get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
5431da177e4SLinus Torvalds cpu->type, &type_name, &var_name);
5441da177e4SLinus Torvalds if (*var_name == '0')
5451da177e4SLinus Torvalds var_name = "";
5461da177e4SLinus Torvalds
5471da177e4SLinus Torvalds if (!vec) {
5481da177e4SLinus Torvalds vec = get_sysvec(hwrpb->sys_type, hwrpb->sys_variation,
5491da177e4SLinus Torvalds cpu->type);
5501da177e4SLinus Torvalds }
5511da177e4SLinus Torvalds
5521da177e4SLinus Torvalds if (!vec) {
5531da177e4SLinus Torvalds panic("Unsupported system type: %s%s%s (%ld %ld)\n",
5541da177e4SLinus Torvalds type_name, (*var_name ? " variation " : ""), var_name,
5551da177e4SLinus Torvalds hwrpb->sys_type, hwrpb->sys_variation);
5561da177e4SLinus Torvalds }
5571da177e4SLinus Torvalds if (vec != &alpha_mv) {
5581da177e4SLinus Torvalds alpha_mv = *vec;
5591da177e4SLinus Torvalds }
5601da177e4SLinus Torvalds
5611da177e4SLinus Torvalds printk("Booting "
5621da177e4SLinus Torvalds #ifdef CONFIG_ALPHA_GENERIC
5631da177e4SLinus Torvalds "GENERIC "
5641da177e4SLinus Torvalds #endif
5651da177e4SLinus Torvalds "on %s%s%s using machine vector %s from %s\n",
5661da177e4SLinus Torvalds type_name, (*var_name ? " variation " : ""),
5671da177e4SLinus Torvalds var_name, alpha_mv.vector_name,
5681da177e4SLinus Torvalds (alpha_using_srm ? "SRM" : "MILO"));
5691da177e4SLinus Torvalds
5701da177e4SLinus Torvalds printk("Major Options: "
5711da177e4SLinus Torvalds #ifdef CONFIG_SMP
5721da177e4SLinus Torvalds "SMP "
5731da177e4SLinus Torvalds #endif
5741da177e4SLinus Torvalds #ifdef CONFIG_ALPHA_EV56
5751da177e4SLinus Torvalds "EV56 "
5761da177e4SLinus Torvalds #endif
5771da177e4SLinus Torvalds #ifdef CONFIG_ALPHA_EV67
5781da177e4SLinus Torvalds "EV67 "
5791da177e4SLinus Torvalds #endif
5801da177e4SLinus Torvalds #ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
5811da177e4SLinus Torvalds "LEGACY_START "
5821da177e4SLinus Torvalds #endif
5831da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
5841da177e4SLinus Torvalds "VERBOSE_MCHECK "
5851da177e4SLinus Torvalds #endif
5861da177e4SLinus Torvalds
5871da177e4SLinus Torvalds #ifdef CONFIG_DEBUG_SPINLOCK
5881da177e4SLinus Torvalds "DEBUG_SPINLOCK "
5891da177e4SLinus Torvalds #endif
5901da177e4SLinus Torvalds #ifdef CONFIG_MAGIC_SYSRQ
5911da177e4SLinus Torvalds "MAGIC_SYSRQ "
5921da177e4SLinus Torvalds #endif
5931da177e4SLinus Torvalds "\n");
5941da177e4SLinus Torvalds
5951da177e4SLinus Torvalds printk("Command line: %s\n", command_line);
5961da177e4SLinus Torvalds
5971da177e4SLinus Torvalds /*
5981da177e4SLinus Torvalds * Sync up the HAE.
5991da177e4SLinus Torvalds * Save the SRM's current value for restoration.
6001da177e4SLinus Torvalds */
6011da177e4SLinus Torvalds srm_hae = *alpha_mv.hae_register;
6021da177e4SLinus Torvalds __set_hae(alpha_mv.hae_cache);
6031da177e4SLinus Torvalds
6041da177e4SLinus Torvalds /* Reset enable correctable error reports. */
6051da177e4SLinus Torvalds wrmces(0x7);
6061da177e4SLinus Torvalds
6071da177e4SLinus Torvalds /* Find our memory. */
6081da177e4SLinus Torvalds setup_memory(kernel_end);
6095b526090SMike Rapoport memblock_set_bottom_up(true);
61036d40290SMike Rapoport sparse_init();
6111da177e4SLinus Torvalds
6121da177e4SLinus Torvalds /* First guess at cpu cache sizes. Do this before init_arch. */
6131da177e4SLinus Torvalds determine_cpu_caches(cpu->type);
6141da177e4SLinus Torvalds
6151da177e4SLinus Torvalds /* Initialize the machine. Usually has to do with setting up
6161da177e4SLinus Torvalds DMA windows and the like. */
6171da177e4SLinus Torvalds if (alpha_mv.init_arch)
6181da177e4SLinus Torvalds alpha_mv.init_arch();
6191da177e4SLinus Torvalds
6201da177e4SLinus Torvalds /* Reserve standard resources. */
6211da177e4SLinus Torvalds reserve_std_resources();
6221da177e4SLinus Torvalds
6231da177e4SLinus Torvalds /*
6241da177e4SLinus Torvalds * Give us a default console. TGA users will see nothing until
6251da177e4SLinus Torvalds * chr_dev_init is called, rather late in the boot sequence.
6261da177e4SLinus Torvalds */
6271da177e4SLinus Torvalds
6281da177e4SLinus Torvalds #ifdef CONFIG_VT
6291da177e4SLinus Torvalds #if defined(CONFIG_VGA_CONSOLE)
630555624c0SArnd Bergmann vgacon_register_screen(&vgacon_screen_info);
6311da177e4SLinus Torvalds #endif
6321da177e4SLinus Torvalds #endif
6331da177e4SLinus Torvalds
6341da177e4SLinus Torvalds /* Default root filesystem to sda2. */
635f5524c3fSChristoph Hellwig ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 2);
6361da177e4SLinus Torvalds
6371da177e4SLinus Torvalds #ifdef CONFIG_EISA
6381da177e4SLinus Torvalds /* FIXME: only set this when we actually have EISA in this box? */
6391da177e4SLinus Torvalds EISA_bus = 1;
6401da177e4SLinus Torvalds #endif
6411da177e4SLinus Torvalds
6421da177e4SLinus Torvalds /*
6431da177e4SLinus Torvalds * Check ASN in HWRPB for validity, report if bad.
6441da177e4SLinus Torvalds * FIXME: how was this failing? Should we trust it instead,
6451da177e4SLinus Torvalds * and copy the value into alpha_mv.max_asn?
6461da177e4SLinus Torvalds */
6471da177e4SLinus Torvalds
6481da177e4SLinus Torvalds if (hwrpb->max_asn != MAX_ASN) {
6491da177e4SLinus Torvalds printk("Max ASN from HWRPB is bad (0x%lx)\n", hwrpb->max_asn);
6501da177e4SLinus Torvalds }
6511da177e4SLinus Torvalds
6521da177e4SLinus Torvalds /*
6531da177e4SLinus Torvalds * Identify the flock of penguins.
6541da177e4SLinus Torvalds */
6551da177e4SLinus Torvalds
6561da177e4SLinus Torvalds #ifdef CONFIG_SMP
6571da177e4SLinus Torvalds setup_smp();
6581da177e4SLinus Torvalds #endif
6591da177e4SLinus Torvalds paging_init();
6601da177e4SLinus Torvalds }
6611da177e4SLinus Torvalds
6621da177e4SLinus Torvalds static char sys_unknown[] = "Unknown";
6631da177e4SLinus Torvalds static char systype_names[][16] = {
6641da177e4SLinus Torvalds "0",
6651da177e4SLinus Torvalds "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
6661da177e4SLinus Torvalds "Pelican", "Morgan", "Sable", "Medulla", "Noname",
6671da177e4SLinus Torvalds "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind",
6681da177e4SLinus Torvalds "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
6691da177e4SLinus Torvalds "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
6701da177e4SLinus Torvalds "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
6711da177e4SLinus Torvalds "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan", "Marvel"
6721da177e4SLinus Torvalds };
6731da177e4SLinus Torvalds
6741da177e4SLinus Torvalds static char unofficial_names[][8] = {"100", "Ruffian"};
6751da177e4SLinus Torvalds
6761da177e4SLinus Torvalds static char api_names[][16] = {"200", "Nautilus"};
6771da177e4SLinus Torvalds
6781da177e4SLinus Torvalds static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164", "RX164"};
6791da177e4SLinus Torvalds static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3,4};
6801da177e4SLinus Torvalds
6811da177e4SLinus Torvalds static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"};
6821da177e4SLinus Torvalds static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
6831da177e4SLinus Torvalds
6841da177e4SLinus Torvalds static char marvel_names[][16] = {
6851da177e4SLinus Torvalds "Marvel/EV7"
6861da177e4SLinus Torvalds };
6871da177e4SLinus Torvalds static int marvel_indices[] = { 0 };
6881da177e4SLinus Torvalds
6891da177e4SLinus Torvalds static char rawhide_names[][16] = {
6901da177e4SLinus Torvalds "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci"
6911da177e4SLinus Torvalds };
6921da177e4SLinus Torvalds static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
6931da177e4SLinus Torvalds
6941da177e4SLinus Torvalds static char titan_names[][16] = {
6951da177e4SLinus Torvalds "DEFAULT", "Privateer", "Falcon", "Granite"
6961da177e4SLinus Torvalds };
6971da177e4SLinus Torvalds static int titan_indices[] = {0,1,2,2,3};
6981da177e4SLinus Torvalds
6991da177e4SLinus Torvalds static char tsunami_names[][16] = {
7001da177e4SLinus Torvalds "0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
7011da177e4SLinus Torvalds "Goldrush", "Webbrick", "Catamaran", "Brisbane", "Melbourne",
7021da177e4SLinus Torvalds "Flying Clipper", "Shark"
7031da177e4SLinus Torvalds };
7041da177e4SLinus Torvalds static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8,9,10,11,12};
7051da177e4SLinus Torvalds
7061da177e4SLinus Torvalds static struct alpha_machine_vector * __init
get_sysvec(unsigned long type,unsigned long variation,unsigned long cpu)7071da177e4SLinus Torvalds get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
7081da177e4SLinus Torvalds {
7091da177e4SLinus Torvalds static struct alpha_machine_vector *systype_vecs[] __initdata =
7101da177e4SLinus Torvalds {
7111da177e4SLinus Torvalds NULL, /* 0 */
7121da177e4SLinus Torvalds NULL, /* ADU */
7131da177e4SLinus Torvalds NULL, /* Cobra */
7141da177e4SLinus Torvalds NULL, /* Ruby */
7151da177e4SLinus Torvalds NULL, /* Flamingo */
7161da177e4SLinus Torvalds NULL, /* Mannequin */
717f81f335aSArnd Bergmann NULL, /* Jensens */
7181da177e4SLinus Torvalds NULL, /* Pelican */
7191da177e4SLinus Torvalds NULL, /* Morgan */
7201da177e4SLinus Torvalds NULL, /* Sable -- see below. */
7211da177e4SLinus Torvalds NULL, /* Medulla */
722*430ad3f0SArnd Bergmann NULL, /* Noname */
7231da177e4SLinus Torvalds NULL, /* Turbolaser */
724*430ad3f0SArnd Bergmann NULL, /* Avanti */
7251da177e4SLinus Torvalds NULL, /* Mustang */
7261da177e4SLinus Torvalds NULL, /* Alcor, Bret, Maverick. HWRPB inaccurate? */
7271da177e4SLinus Torvalds NULL, /* Tradewind */
7281da177e4SLinus Torvalds NULL, /* Mikasa -- see below. */
7291da177e4SLinus Torvalds NULL, /* EB64 */
730*430ad3f0SArnd Bergmann NULL, /* EB66 */
731*430ad3f0SArnd Bergmann NULL, /* EB64+ */
732*430ad3f0SArnd Bergmann NULL, /* Alphabook1 */
7331da177e4SLinus Torvalds &rawhide_mv,
7341da177e4SLinus Torvalds NULL, /* K2 */
735d2b1e353SArnd Bergmann NULL, /* Lynx */
736*430ad3f0SArnd Bergmann NULL, /* XL */
7371da177e4SLinus Torvalds NULL, /* EB164 -- see variation. */
7381da177e4SLinus Torvalds NULL, /* Noritake -- see below. */
7391da177e4SLinus Torvalds NULL, /* Cortex */
7401da177e4SLinus Torvalds NULL, /* 29 */
7411da177e4SLinus Torvalds &miata_mv,
7421da177e4SLinus Torvalds NULL, /* XXM */
7431da177e4SLinus Torvalds &takara_mv,
7441da177e4SLinus Torvalds NULL, /* Yukon */
7451da177e4SLinus Torvalds NULL, /* Tsunami -- see variation. */
7461da177e4SLinus Torvalds &wildfire_mv, /* Wildfire */
7471da177e4SLinus Torvalds NULL, /* CUSCO */
7481da177e4SLinus Torvalds &eiger_mv, /* Eiger */
7491da177e4SLinus Torvalds NULL, /* Titan */
7501da177e4SLinus Torvalds NULL, /* Marvel */
7511da177e4SLinus Torvalds };
7521da177e4SLinus Torvalds
7531da177e4SLinus Torvalds static struct alpha_machine_vector *unofficial_vecs[] __initdata =
7541da177e4SLinus Torvalds {
7551da177e4SLinus Torvalds NULL, /* 100 */
7561da177e4SLinus Torvalds &ruffian_mv,
7571da177e4SLinus Torvalds };
7581da177e4SLinus Torvalds
7591da177e4SLinus Torvalds static struct alpha_machine_vector *api_vecs[] __initdata =
7601da177e4SLinus Torvalds {
7611da177e4SLinus Torvalds NULL, /* 200 */
7621da177e4SLinus Torvalds &nautilus_mv,
7631da177e4SLinus Torvalds };
7641da177e4SLinus Torvalds
7651da177e4SLinus Torvalds static struct alpha_machine_vector *alcor_vecs[] __initdata =
7661da177e4SLinus Torvalds {
7671da177e4SLinus Torvalds &alcor_mv, &xlt_mv, &xlt_mv
7681da177e4SLinus Torvalds };
7691da177e4SLinus Torvalds
7701da177e4SLinus Torvalds static struct alpha_machine_vector *eb164_vecs[] __initdata =
7711da177e4SLinus Torvalds {
7721da177e4SLinus Torvalds &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv, &rx164_mv
7731da177e4SLinus Torvalds };
7741da177e4SLinus Torvalds
7751da177e4SLinus Torvalds static struct alpha_machine_vector *marvel_vecs[] __initdata =
7761da177e4SLinus Torvalds {
7771da177e4SLinus Torvalds &marvel_ev7_mv,
7781da177e4SLinus Torvalds };
7791da177e4SLinus Torvalds
7801da177e4SLinus Torvalds static struct alpha_machine_vector *titan_vecs[] __initdata =
7811da177e4SLinus Torvalds {
7821da177e4SLinus Torvalds &titan_mv, /* default */
7831da177e4SLinus Torvalds &privateer_mv, /* privateer */
7841da177e4SLinus Torvalds &titan_mv, /* falcon */
7851da177e4SLinus Torvalds &privateer_mv, /* granite */
7861da177e4SLinus Torvalds };
7871da177e4SLinus Torvalds
7881da177e4SLinus Torvalds static struct alpha_machine_vector *tsunami_vecs[] __initdata =
7891da177e4SLinus Torvalds {
7901da177e4SLinus Torvalds NULL,
7911da177e4SLinus Torvalds &dp264_mv, /* dp264 */
7921da177e4SLinus Torvalds &dp264_mv, /* warhol */
7931da177e4SLinus Torvalds &dp264_mv, /* windjammer */
7941da177e4SLinus Torvalds &monet_mv, /* monet */
7951da177e4SLinus Torvalds &clipper_mv, /* clipper */
7961da177e4SLinus Torvalds &dp264_mv, /* goldrush */
7971da177e4SLinus Torvalds &webbrick_mv, /* webbrick */
7981da177e4SLinus Torvalds &dp264_mv, /* catamaran */
7991da177e4SLinus Torvalds NULL, /* brisbane? */
8001da177e4SLinus Torvalds NULL, /* melbourne? */
8011da177e4SLinus Torvalds NULL, /* flying clipper? */
8021da177e4SLinus Torvalds &shark_mv, /* shark */
8031da177e4SLinus Torvalds };
8041da177e4SLinus Torvalds
8051da177e4SLinus Torvalds /* ??? Do we need to distinguish between Rawhides? */
8061da177e4SLinus Torvalds
8071da177e4SLinus Torvalds struct alpha_machine_vector *vec;
8081da177e4SLinus Torvalds
8091da177e4SLinus Torvalds /* Search the system tables first... */
8101da177e4SLinus Torvalds vec = NULL;
81125c8716cSTobias Klauser if (type < ARRAY_SIZE(systype_vecs)) {
8121da177e4SLinus Torvalds vec = systype_vecs[type];
8131da177e4SLinus Torvalds } else if ((type > ST_API_BIAS) &&
81425c8716cSTobias Klauser (type - ST_API_BIAS) < ARRAY_SIZE(api_vecs)) {
8151da177e4SLinus Torvalds vec = api_vecs[type - ST_API_BIAS];
8161da177e4SLinus Torvalds } else if ((type > ST_UNOFFICIAL_BIAS) &&
81725c8716cSTobias Klauser (type - ST_UNOFFICIAL_BIAS) < ARRAY_SIZE(unofficial_vecs)) {
8181da177e4SLinus Torvalds vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS];
8191da177e4SLinus Torvalds }
8201da177e4SLinus Torvalds
8211da177e4SLinus Torvalds /* If we've not found one, try for a variation. */
8221da177e4SLinus Torvalds
8231da177e4SLinus Torvalds if (!vec) {
8241da177e4SLinus Torvalds /* Member ID is a bit-field. */
8251da177e4SLinus Torvalds unsigned long member = (variation >> 10) & 0x3f;
8261da177e4SLinus Torvalds
8271da177e4SLinus Torvalds cpu &= 0xffffffff; /* make it usable */
8281da177e4SLinus Torvalds
8291da177e4SLinus Torvalds switch (type) {
8301da177e4SLinus Torvalds case ST_DEC_ALCOR:
83125c8716cSTobias Klauser if (member < ARRAY_SIZE(alcor_indices))
8321da177e4SLinus Torvalds vec = alcor_vecs[alcor_indices[member]];
8331da177e4SLinus Torvalds break;
8341da177e4SLinus Torvalds case ST_DEC_EB164:
83525c8716cSTobias Klauser if (member < ARRAY_SIZE(eb164_indices))
8361da177e4SLinus Torvalds vec = eb164_vecs[eb164_indices[member]];
8371da177e4SLinus Torvalds /* PC164 may show as EB164 variation with EV56 CPU,
8381da177e4SLinus Torvalds but, since no true EB164 had anything but EV5... */
8391da177e4SLinus Torvalds if (vec == &eb164_mv && cpu == EV56_CPU)
8401da177e4SLinus Torvalds vec = &pc164_mv;
8411da177e4SLinus Torvalds break;
8421da177e4SLinus Torvalds case ST_DEC_MARVEL:
84325c8716cSTobias Klauser if (member < ARRAY_SIZE(marvel_indices))
8441da177e4SLinus Torvalds vec = marvel_vecs[marvel_indices[member]];
8451da177e4SLinus Torvalds break;
8461da177e4SLinus Torvalds case ST_DEC_TITAN:
8471da177e4SLinus Torvalds vec = titan_vecs[0]; /* default */
84825c8716cSTobias Klauser if (member < ARRAY_SIZE(titan_indices))
8491da177e4SLinus Torvalds vec = titan_vecs[titan_indices[member]];
8501da177e4SLinus Torvalds break;
8511da177e4SLinus Torvalds case ST_DEC_TSUNAMI:
85225c8716cSTobias Klauser if (member < ARRAY_SIZE(tsunami_indices))
8531da177e4SLinus Torvalds vec = tsunami_vecs[tsunami_indices[member]];
8541da177e4SLinus Torvalds break;
8551da177e4SLinus Torvalds case ST_DEC_1000:
8561da177e4SLinus Torvalds vec = &mikasa_primo_mv;
8571da177e4SLinus Torvalds break;
8581da177e4SLinus Torvalds case ST_DEC_NORITAKE:
8591da177e4SLinus Torvalds vec = &noritake_primo_mv;
8601da177e4SLinus Torvalds break;
8611da177e4SLinus Torvalds case ST_DEC_2100_A500:
8621da177e4SLinus Torvalds vec = &sable_gamma_mv;
8631da177e4SLinus Torvalds break;
8641da177e4SLinus Torvalds }
8651da177e4SLinus Torvalds }
8661da177e4SLinus Torvalds return vec;
8671da177e4SLinus Torvalds }
8681da177e4SLinus Torvalds
8691da177e4SLinus Torvalds static struct alpha_machine_vector * __init
get_sysvec_byname(const char * name)8701da177e4SLinus Torvalds get_sysvec_byname(const char *name)
8711da177e4SLinus Torvalds {
8721da177e4SLinus Torvalds static struct alpha_machine_vector *all_vecs[] __initdata =
8731da177e4SLinus Torvalds {
8741da177e4SLinus Torvalds &alcor_mv,
8751da177e4SLinus Torvalds &clipper_mv,
8761da177e4SLinus Torvalds &dp264_mv,
8771da177e4SLinus Torvalds &eb164_mv,
8781da177e4SLinus Torvalds &eiger_mv,
8791da177e4SLinus Torvalds &lx164_mv,
8801da177e4SLinus Torvalds &miata_mv,
8811da177e4SLinus Torvalds &mikasa_primo_mv,
8821da177e4SLinus Torvalds &monet_mv,
8831da177e4SLinus Torvalds &nautilus_mv,
8841da177e4SLinus Torvalds &noritake_primo_mv,
8851da177e4SLinus Torvalds &pc164_mv,
8861da177e4SLinus Torvalds &privateer_mv,
8871da177e4SLinus Torvalds &rawhide_mv,
8881da177e4SLinus Torvalds &ruffian_mv,
8891da177e4SLinus Torvalds &rx164_mv,
8901da177e4SLinus Torvalds &sable_gamma_mv,
8911da177e4SLinus Torvalds &shark_mv,
8921da177e4SLinus Torvalds &sx164_mv,
8931da177e4SLinus Torvalds &takara_mv,
8941da177e4SLinus Torvalds &webbrick_mv,
8951da177e4SLinus Torvalds &wildfire_mv,
8961da177e4SLinus Torvalds &xlt_mv
8971da177e4SLinus Torvalds };
8981da177e4SLinus Torvalds
8991da177e4SLinus Torvalds size_t i;
9001da177e4SLinus Torvalds
90125c8716cSTobias Klauser for (i = 0; i < ARRAY_SIZE(all_vecs); ++i) {
9021da177e4SLinus Torvalds struct alpha_machine_vector *mv = all_vecs[i];
9031da177e4SLinus Torvalds if (strcasecmp(mv->vector_name, name) == 0)
9041da177e4SLinus Torvalds return mv;
9051da177e4SLinus Torvalds }
9061da177e4SLinus Torvalds return NULL;
9071da177e4SLinus Torvalds }
9081da177e4SLinus Torvalds
9091da177e4SLinus Torvalds static void
get_sysnames(unsigned long type,unsigned long variation,unsigned long cpu,char ** type_name,char ** variation_name)9101da177e4SLinus Torvalds get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
9111da177e4SLinus Torvalds char **type_name, char **variation_name)
9121da177e4SLinus Torvalds {
9131da177e4SLinus Torvalds unsigned long member;
9141da177e4SLinus Torvalds
9151da177e4SLinus Torvalds /* If not in the tables, make it UNKNOWN,
9161da177e4SLinus Torvalds else set type name to family */
91725c8716cSTobias Klauser if (type < ARRAY_SIZE(systype_names)) {
9181da177e4SLinus Torvalds *type_name = systype_names[type];
9191da177e4SLinus Torvalds } else if ((type > ST_API_BIAS) &&
92025c8716cSTobias Klauser (type - ST_API_BIAS) < ARRAY_SIZE(api_names)) {
9211da177e4SLinus Torvalds *type_name = api_names[type - ST_API_BIAS];
9221da177e4SLinus Torvalds } else if ((type > ST_UNOFFICIAL_BIAS) &&
92325c8716cSTobias Klauser (type - ST_UNOFFICIAL_BIAS) < ARRAY_SIZE(unofficial_names)) {
9241da177e4SLinus Torvalds *type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS];
9251da177e4SLinus Torvalds } else {
9261da177e4SLinus Torvalds *type_name = sys_unknown;
9271da177e4SLinus Torvalds *variation_name = sys_unknown;
9281da177e4SLinus Torvalds return;
9291da177e4SLinus Torvalds }
9301da177e4SLinus Torvalds
9311da177e4SLinus Torvalds /* Set variation to "0"; if variation is zero, done. */
9321da177e4SLinus Torvalds *variation_name = systype_names[0];
9331da177e4SLinus Torvalds if (variation == 0) {
9341da177e4SLinus Torvalds return;
9351da177e4SLinus Torvalds }
9361da177e4SLinus Torvalds
9371da177e4SLinus Torvalds member = (variation >> 10) & 0x3f; /* member ID is a bit-field */
9381da177e4SLinus Torvalds
9391da177e4SLinus Torvalds cpu &= 0xffffffff; /* make it usable */
9401da177e4SLinus Torvalds
9411da177e4SLinus Torvalds switch (type) { /* select by family */
9421da177e4SLinus Torvalds default: /* default to variation "0" for now */
9431da177e4SLinus Torvalds break;
9441da177e4SLinus Torvalds case ST_DEC_EB164:
94503e1f044SDan Carpenter if (member >= ARRAY_SIZE(eb164_indices))
94603e1f044SDan Carpenter break;
9471da177e4SLinus Torvalds *variation_name = eb164_names[eb164_indices[member]];
9481da177e4SLinus Torvalds /* PC164 may show as EB164 variation, but with EV56 CPU,
9491da177e4SLinus Torvalds so, since no true EB164 had anything but EV5... */
9501da177e4SLinus Torvalds if (eb164_indices[member] == 0 && cpu == EV56_CPU)
9511da177e4SLinus Torvalds *variation_name = eb164_names[1]; /* make it PC164 */
9521da177e4SLinus Torvalds break;
9531da177e4SLinus Torvalds case ST_DEC_ALCOR:
95425c8716cSTobias Klauser if (member < ARRAY_SIZE(alcor_indices))
9551da177e4SLinus Torvalds *variation_name = alcor_names[alcor_indices[member]];
9561da177e4SLinus Torvalds break;
9571da177e4SLinus Torvalds case ST_DEC_MARVEL:
95825c8716cSTobias Klauser if (member < ARRAY_SIZE(marvel_indices))
9591da177e4SLinus Torvalds *variation_name = marvel_names[marvel_indices[member]];
9601da177e4SLinus Torvalds break;
9611da177e4SLinus Torvalds case ST_DEC_RAWHIDE:
96225c8716cSTobias Klauser if (member < ARRAY_SIZE(rawhide_indices))
9631da177e4SLinus Torvalds *variation_name = rawhide_names[rawhide_indices[member]];
9641da177e4SLinus Torvalds break;
9651da177e4SLinus Torvalds case ST_DEC_TITAN:
9661da177e4SLinus Torvalds *variation_name = titan_names[0]; /* default */
96725c8716cSTobias Klauser if (member < ARRAY_SIZE(titan_indices))
9681da177e4SLinus Torvalds *variation_name = titan_names[titan_indices[member]];
9691da177e4SLinus Torvalds break;
9701da177e4SLinus Torvalds case ST_DEC_TSUNAMI:
97125c8716cSTobias Klauser if (member < ARRAY_SIZE(tsunami_indices))
9721da177e4SLinus Torvalds *variation_name = tsunami_names[tsunami_indices[member]];
9731da177e4SLinus Torvalds break;
9741da177e4SLinus Torvalds }
9751da177e4SLinus Torvalds }
9761da177e4SLinus Torvalds
9771da177e4SLinus Torvalds /*
9781da177e4SLinus Torvalds * A change was made to the HWRPB via an ECO and the following code
9791da177e4SLinus Torvalds * tracks a part of the ECO. In HWRPB versions less than 5, the ECO
9801da177e4SLinus Torvalds * was not implemented in the console firmware. If it's revision 5 or
9811da177e4SLinus Torvalds * greater we can get the name of the platform as an ASCII string from
9821da177e4SLinus Torvalds * the HWRPB. That's what this function does. It checks the revision
9831da177e4SLinus Torvalds * level and if the string is in the HWRPB it returns the address of
9841da177e4SLinus Torvalds * the string--a pointer to the name of the platform.
9851da177e4SLinus Torvalds *
9861da177e4SLinus Torvalds * Returns:
9871da177e4SLinus Torvalds * - Pointer to a ASCII string if it's in the HWRPB
9881da177e4SLinus Torvalds * - Pointer to a blank string if the data is not in the HWRPB.
9891da177e4SLinus Torvalds */
9901da177e4SLinus Torvalds
9911da177e4SLinus Torvalds static char *
platform_string(void)9921da177e4SLinus Torvalds platform_string(void)
9931da177e4SLinus Torvalds {
9941da177e4SLinus Torvalds struct dsr_struct *dsr;
9951da177e4SLinus Torvalds static char unk_system_string[] = "N/A";
9961da177e4SLinus Torvalds
9971da177e4SLinus Torvalds /* Go to the console for the string pointer.
9981da177e4SLinus Torvalds * If the rpb_vers is not 5 or greater the rpb
9991da177e4SLinus Torvalds * is old and does not have this data in it.
10001da177e4SLinus Torvalds */
10011da177e4SLinus Torvalds if (hwrpb->revision < 5)
10021da177e4SLinus Torvalds return (unk_system_string);
10031da177e4SLinus Torvalds else {
10041da177e4SLinus Torvalds /* The Dynamic System Recognition struct
10051da177e4SLinus Torvalds * has the system platform name starting
10061da177e4SLinus Torvalds * after the character count of the string.
10071da177e4SLinus Torvalds */
10081da177e4SLinus Torvalds dsr = ((struct dsr_struct *)
10091da177e4SLinus Torvalds ((char *)hwrpb + hwrpb->dsr_offset));
10101da177e4SLinus Torvalds return ((char *)dsr + (dsr->sysname_off +
10111da177e4SLinus Torvalds sizeof(long)));
10121da177e4SLinus Torvalds }
10131da177e4SLinus Torvalds }
10141da177e4SLinus Torvalds
10151da177e4SLinus Torvalds static int
get_nr_processors(struct percpu_struct * cpubase,unsigned long num)10161da177e4SLinus Torvalds get_nr_processors(struct percpu_struct *cpubase, unsigned long num)
10171da177e4SLinus Torvalds {
10181da177e4SLinus Torvalds struct percpu_struct *cpu;
10191da177e4SLinus Torvalds unsigned long i;
10201da177e4SLinus Torvalds int count = 0;
10211da177e4SLinus Torvalds
10221da177e4SLinus Torvalds for (i = 0; i < num; i++) {
10231da177e4SLinus Torvalds cpu = (struct percpu_struct *)
10241da177e4SLinus Torvalds ((char *)cpubase + i*hwrpb->processor_size);
10251da177e4SLinus Torvalds if ((cpu->flags & 0x1cc) == 0x1cc)
10261da177e4SLinus Torvalds count++;
10271da177e4SLinus Torvalds }
10281da177e4SLinus Torvalds return count;
10291da177e4SLinus Torvalds }
10301da177e4SLinus Torvalds
10311da177e4SLinus Torvalds static void
show_cache_size(struct seq_file * f,const char * which,int shape)10321da177e4SLinus Torvalds show_cache_size (struct seq_file *f, const char *which, int shape)
10331da177e4SLinus Torvalds {
10341da177e4SLinus Torvalds if (shape == -1)
10351da177e4SLinus Torvalds seq_printf (f, "%s\t\t: n/a\n", which);
10361da177e4SLinus Torvalds else if (shape == 0)
10371da177e4SLinus Torvalds seq_printf (f, "%s\t\t: unknown\n", which);
10381da177e4SLinus Torvalds else
10391da177e4SLinus Torvalds seq_printf (f, "%s\t\t: %dK, %d-way, %db line\n",
10401da177e4SLinus Torvalds which, shape >> 10, shape & 15,
10411da177e4SLinus Torvalds 1 << ((shape >> 4) & 15));
10421da177e4SLinus Torvalds }
10431da177e4SLinus Torvalds
10441da177e4SLinus Torvalds static int
show_cpuinfo(struct seq_file * f,void * slot)10451da177e4SLinus Torvalds show_cpuinfo(struct seq_file *f, void *slot)
10461da177e4SLinus Torvalds {
10471da177e4SLinus Torvalds extern struct unaligned_stat {
10481da177e4SLinus Torvalds unsigned long count, va, pc;
10491da177e4SLinus Torvalds } unaligned[2];
10501da177e4SLinus Torvalds
10511da177e4SLinus Torvalds static char cpu_names[][8] = {
10521da177e4SLinus Torvalds "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56",
10531da177e4SLinus Torvalds "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL",
10541da177e4SLinus Torvalds "EV68CX", "EV7", "EV79", "EV69"
10551da177e4SLinus Torvalds };
10561da177e4SLinus Torvalds
10571da177e4SLinus Torvalds struct percpu_struct *cpu = slot;
10581da177e4SLinus Torvalds unsigned int cpu_index;
10591da177e4SLinus Torvalds char *cpu_name;
10601da177e4SLinus Torvalds char *systype_name;
10611da177e4SLinus Torvalds char *sysvariation_name;
10621da177e4SLinus Torvalds int nr_processors;
1063fddd87d6SRichard Henderson unsigned long timer_freq;
10641da177e4SLinus Torvalds
10651da177e4SLinus Torvalds cpu_index = (unsigned) (cpu->type - 1);
10661da177e4SLinus Torvalds cpu_name = "Unknown";
106725c8716cSTobias Klauser if (cpu_index < ARRAY_SIZE(cpu_names))
10681da177e4SLinus Torvalds cpu_name = cpu_names[cpu_index];
10691da177e4SLinus Torvalds
10701da177e4SLinus Torvalds get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
10711da177e4SLinus Torvalds cpu->type, &systype_name, &sysvariation_name);
10721da177e4SLinus Torvalds
10731da177e4SLinus Torvalds nr_processors = get_nr_processors(cpu, hwrpb->nr_processors);
10741da177e4SLinus Torvalds
1075fddd87d6SRichard Henderson #if CONFIG_HZ == 1024 || CONFIG_HZ == 1200
1076fddd87d6SRichard Henderson timer_freq = (100UL * hwrpb->intr_freq) / 4096;
1077fddd87d6SRichard Henderson #else
1078fddd87d6SRichard Henderson timer_freq = 100UL * CONFIG_HZ;
1079fddd87d6SRichard Henderson #endif
1080fddd87d6SRichard Henderson
10811da177e4SLinus Torvalds seq_printf(f, "cpu\t\t\t: Alpha\n"
10821da177e4SLinus Torvalds "cpu model\t\t: %s\n"
10831da177e4SLinus Torvalds "cpu variation\t\t: %ld\n"
10841da177e4SLinus Torvalds "cpu revision\t\t: %ld\n"
10851da177e4SLinus Torvalds "cpu serial number\t: %s\n"
10861da177e4SLinus Torvalds "system type\t\t: %s\n"
10871da177e4SLinus Torvalds "system variation\t: %s\n"
10881da177e4SLinus Torvalds "system revision\t\t: %ld\n"
10891da177e4SLinus Torvalds "system serial number\t: %s\n"
10901da177e4SLinus Torvalds "cycle frequency [Hz]\t: %lu %s\n"
10911da177e4SLinus Torvalds "timer frequency [Hz]\t: %lu.%02lu\n"
10921da177e4SLinus Torvalds "page size [bytes]\t: %ld\n"
10931da177e4SLinus Torvalds "phys. address bits\t: %ld\n"
10941da177e4SLinus Torvalds "max. addr. space #\t: %ld\n"
10951da177e4SLinus Torvalds "BogoMIPS\t\t: %lu.%02lu\n"
10961da177e4SLinus Torvalds "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
10971da177e4SLinus Torvalds "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
10981da177e4SLinus Torvalds "platform string\t\t: %s\n"
10991da177e4SLinus Torvalds "cpus detected\t\t: %d\n",
11001da177e4SLinus Torvalds cpu_name, cpu->variation, cpu->revision,
11011da177e4SLinus Torvalds (char*)cpu->serial_no,
11021da177e4SLinus Torvalds systype_name, sysvariation_name, hwrpb->sys_revision,
11031da177e4SLinus Torvalds (char*)hwrpb->ssn,
11041da177e4SLinus Torvalds est_cycle_freq ? : hwrpb->cycle_freq,
11051da177e4SLinus Torvalds est_cycle_freq ? "est." : "",
1106fddd87d6SRichard Henderson timer_freq / 100, timer_freq % 100,
11071da177e4SLinus Torvalds hwrpb->pagesize,
11081da177e4SLinus Torvalds hwrpb->pa_bits,
11091da177e4SLinus Torvalds hwrpb->max_asn,
11101da177e4SLinus Torvalds loops_per_jiffy / (500000/HZ),
11111da177e4SLinus Torvalds (loops_per_jiffy / (5000/HZ)) % 100,
11121da177e4SLinus Torvalds unaligned[0].count, unaligned[0].pc, unaligned[0].va,
11131da177e4SLinus Torvalds unaligned[1].count, unaligned[1].pc, unaligned[1].va,
11141da177e4SLinus Torvalds platform_string(), nr_processors);
11151da177e4SLinus Torvalds
11161da177e4SLinus Torvalds #ifdef CONFIG_SMP
11175f0e3da6SRandy Dunlap seq_printf(f, "cpus active\t\t: %u\n"
11181da177e4SLinus Torvalds "cpu active mask\t\t: %016lx\n",
111981740fc6SKOSAKI Motohiro num_online_cpus(), cpumask_bits(cpu_possible_mask)[0]);
11201da177e4SLinus Torvalds #endif
11211da177e4SLinus Torvalds
11221da177e4SLinus Torvalds show_cache_size (f, "L1 Icache", alpha_l1i_cacheshape);
11231da177e4SLinus Torvalds show_cache_size (f, "L1 Dcache", alpha_l1d_cacheshape);
11241da177e4SLinus Torvalds show_cache_size (f, "L2 cache", alpha_l2_cacheshape);
11251da177e4SLinus Torvalds show_cache_size (f, "L3 cache", alpha_l3_cacheshape);
11261da177e4SLinus Torvalds
11271da177e4SLinus Torvalds return 0;
11281da177e4SLinus Torvalds }
11291da177e4SLinus Torvalds
11301da177e4SLinus Torvalds static int __init
read_mem_block(int * addr,int stride,int size)11311da177e4SLinus Torvalds read_mem_block(int *addr, int stride, int size)
11321da177e4SLinus Torvalds {
11331da177e4SLinus Torvalds long nloads = size / stride, cnt, tmp;
11341da177e4SLinus Torvalds
11351da177e4SLinus Torvalds __asm__ __volatile__(
11361da177e4SLinus Torvalds " rpcc %0\n"
11371da177e4SLinus Torvalds "1: ldl %3,0(%2)\n"
11381da177e4SLinus Torvalds " subq %1,1,%1\n"
11391da177e4SLinus Torvalds /* Next two XORs introduce an explicit data dependency between
11401da177e4SLinus Torvalds consecutive loads in the loop, which will give us true load
11411da177e4SLinus Torvalds latency. */
11421da177e4SLinus Torvalds " xor %3,%2,%2\n"
11431da177e4SLinus Torvalds " xor %3,%2,%2\n"
11441da177e4SLinus Torvalds " addq %2,%4,%2\n"
11451da177e4SLinus Torvalds " bne %1,1b\n"
11461da177e4SLinus Torvalds " rpcc %3\n"
11471da177e4SLinus Torvalds " subl %3,%0,%0\n"
11481da177e4SLinus Torvalds : "=&r" (cnt), "=&r" (nloads), "=&r" (addr), "=&r" (tmp)
11491da177e4SLinus Torvalds : "r" (stride), "1" (nloads), "2" (addr));
11501da177e4SLinus Torvalds
11511da177e4SLinus Torvalds return cnt / (size / stride);
11521da177e4SLinus Torvalds }
11531da177e4SLinus Torvalds
11541da177e4SLinus Torvalds #define CSHAPE(totalsize, linesize, assoc) \
11551da177e4SLinus Torvalds ((totalsize & ~0xff) | (linesize << 4) | assoc)
11561da177e4SLinus Torvalds
11571da177e4SLinus Torvalds /* ??? EV5 supports up to 64M, but did the systems with more than
11581da177e4SLinus Torvalds 16M of BCACHE ever exist? */
11591da177e4SLinus Torvalds #define MAX_BCACHE_SIZE 16*1024*1024
11601da177e4SLinus Torvalds
11611da177e4SLinus Torvalds /* Note that the offchip caches are direct mapped on all Alphas. */
11621da177e4SLinus Torvalds static int __init
external_cache_probe(int minsize,int width)11631da177e4SLinus Torvalds external_cache_probe(int minsize, int width)
11641da177e4SLinus Torvalds {
11651da177e4SLinus Torvalds int cycles, prev_cycles = 1000000;
11661da177e4SLinus Torvalds int stride = 1 << width;
11671da177e4SLinus Torvalds long size = minsize, maxsize = MAX_BCACHE_SIZE * 2;
11681da177e4SLinus Torvalds
11691da177e4SLinus Torvalds if (maxsize > (max_low_pfn + 1) << PAGE_SHIFT)
117074fd1b68SRichard Henderson maxsize = 1 << (ilog2(max_low_pfn + 1) + PAGE_SHIFT);
11711da177e4SLinus Torvalds
11721da177e4SLinus Torvalds /* Get the first block cached. */
11731da177e4SLinus Torvalds read_mem_block(__va(0), stride, size);
11741da177e4SLinus Torvalds
11751da177e4SLinus Torvalds while (size < maxsize) {
11761da177e4SLinus Torvalds /* Get an average load latency in cycles. */
11771da177e4SLinus Torvalds cycles = read_mem_block(__va(0), stride, size);
11781da177e4SLinus Torvalds if (cycles > prev_cycles * 2) {
11791da177e4SLinus Torvalds /* Fine, we exceed the cache. */
11801da177e4SLinus Torvalds printk("%ldK Bcache detected; load hit latency %d "
11811da177e4SLinus Torvalds "cycles, load miss latency %d cycles\n",
11821da177e4SLinus Torvalds size >> 11, prev_cycles, cycles);
11831da177e4SLinus Torvalds return CSHAPE(size >> 1, width, 1);
11841da177e4SLinus Torvalds }
11851da177e4SLinus Torvalds /* Try to get the next block cached. */
11861da177e4SLinus Torvalds read_mem_block(__va(size), stride, size);
11871da177e4SLinus Torvalds prev_cycles = cycles;
11881da177e4SLinus Torvalds size <<= 1;
11891da177e4SLinus Torvalds }
11901da177e4SLinus Torvalds return -1; /* No BCACHE found. */
11911da177e4SLinus Torvalds }
11921da177e4SLinus Torvalds
11931da177e4SLinus Torvalds static void __init
determine_cpu_caches(unsigned int cpu_type)11941da177e4SLinus Torvalds determine_cpu_caches (unsigned int cpu_type)
11951da177e4SLinus Torvalds {
11961da177e4SLinus Torvalds int L1I, L1D, L2, L3;
11971da177e4SLinus Torvalds
11981da177e4SLinus Torvalds switch (cpu_type) {
11991da177e4SLinus Torvalds case EV4_CPU:
12001da177e4SLinus Torvalds case EV45_CPU:
12011da177e4SLinus Torvalds {
12021da177e4SLinus Torvalds if (cpu_type == EV4_CPU)
12031da177e4SLinus Torvalds L1I = CSHAPE(8*1024, 5, 1);
12041da177e4SLinus Torvalds else
12051da177e4SLinus Torvalds L1I = CSHAPE(16*1024, 5, 1);
12061da177e4SLinus Torvalds L1D = L1I;
12071da177e4SLinus Torvalds L3 = -1;
12081da177e4SLinus Torvalds
12091da177e4SLinus Torvalds /* BIU_CTL is a write-only Abox register. PALcode has a
12101da177e4SLinus Torvalds shadow copy, and may be available from some versions
12111da177e4SLinus Torvalds of the CSERVE PALcall. If we can get it, then
12121da177e4SLinus Torvalds
12131da177e4SLinus Torvalds unsigned long biu_ctl, size;
12141da177e4SLinus Torvalds size = 128*1024 * (1 << ((biu_ctl >> 28) & 7));
12151da177e4SLinus Torvalds L2 = CSHAPE (size, 5, 1);
12161da177e4SLinus Torvalds
12171da177e4SLinus Torvalds Unfortunately, we can't rely on that.
12181da177e4SLinus Torvalds */
12191da177e4SLinus Torvalds L2 = external_cache_probe(128*1024, 5);
12201da177e4SLinus Torvalds break;
12211da177e4SLinus Torvalds }
12221da177e4SLinus Torvalds
12231da177e4SLinus Torvalds case LCA4_CPU:
12241da177e4SLinus Torvalds {
12251da177e4SLinus Torvalds unsigned long car, size;
12261da177e4SLinus Torvalds
12271da177e4SLinus Torvalds L1I = L1D = CSHAPE(8*1024, 5, 1);
12281da177e4SLinus Torvalds L3 = -1;
12291da177e4SLinus Torvalds
12301da177e4SLinus Torvalds car = *(vuip) phys_to_virt (0x120000078UL);
12311da177e4SLinus Torvalds size = 64*1024 * (1 << ((car >> 5) & 7));
12321da177e4SLinus Torvalds /* No typo -- 8 byte cacheline size. Whodathunk. */
12331da177e4SLinus Torvalds L2 = (car & 1 ? CSHAPE (size, 3, 1) : -1);
12341da177e4SLinus Torvalds break;
12351da177e4SLinus Torvalds }
12361da177e4SLinus Torvalds
12371da177e4SLinus Torvalds case EV5_CPU:
12381da177e4SLinus Torvalds case EV56_CPU:
12391da177e4SLinus Torvalds {
12401da177e4SLinus Torvalds unsigned long sc_ctl, width;
12411da177e4SLinus Torvalds
12421da177e4SLinus Torvalds L1I = L1D = CSHAPE(8*1024, 5, 1);
12431da177e4SLinus Torvalds
12441da177e4SLinus Torvalds /* Check the line size of the Scache. */
12451da177e4SLinus Torvalds sc_ctl = *(vulp) phys_to_virt (0xfffff000a8UL);
12461da177e4SLinus Torvalds width = sc_ctl & 0x1000 ? 6 : 5;
12471da177e4SLinus Torvalds L2 = CSHAPE (96*1024, width, 3);
12481da177e4SLinus Torvalds
12491da177e4SLinus Torvalds /* BC_CONTROL and BC_CONFIG are write-only IPRs. PALcode
12501da177e4SLinus Torvalds has a shadow copy, and may be available from some versions
12511da177e4SLinus Torvalds of the CSERVE PALcall. If we can get it, then
12521da177e4SLinus Torvalds
12531da177e4SLinus Torvalds unsigned long bc_control, bc_config, size;
12541da177e4SLinus Torvalds size = 1024*1024 * (1 << ((bc_config & 7) - 1));
12551da177e4SLinus Torvalds L3 = (bc_control & 1 ? CSHAPE (size, width, 1) : -1);
12561da177e4SLinus Torvalds
12571da177e4SLinus Torvalds Unfortunately, we can't rely on that.
12581da177e4SLinus Torvalds */
12591da177e4SLinus Torvalds L3 = external_cache_probe(1024*1024, width);
12601da177e4SLinus Torvalds break;
12611da177e4SLinus Torvalds }
12621da177e4SLinus Torvalds
12631da177e4SLinus Torvalds case PCA56_CPU:
12641da177e4SLinus Torvalds case PCA57_CPU:
12651da177e4SLinus Torvalds {
12661da177e4SLinus Torvalds if (cpu_type == PCA56_CPU) {
12671da177e4SLinus Torvalds L1I = CSHAPE(16*1024, 6, 1);
12681da177e4SLinus Torvalds L1D = CSHAPE(8*1024, 5, 1);
12691da177e4SLinus Torvalds } else {
12701da177e4SLinus Torvalds L1I = CSHAPE(32*1024, 6, 2);
12711da177e4SLinus Torvalds L1D = CSHAPE(16*1024, 5, 1);
12721da177e4SLinus Torvalds }
12731da177e4SLinus Torvalds L3 = -1;
12741da177e4SLinus Torvalds
1275280da4e4SRichard Henderson #if 0
1276280da4e4SRichard Henderson unsigned long cbox_config, size;
1277280da4e4SRichard Henderson
12781da177e4SLinus Torvalds cbox_config = *(vulp) phys_to_virt (0xfffff00008UL);
12791da177e4SLinus Torvalds size = 512*1024 * (1 << ((cbox_config >> 12) & 3));
12801da177e4SLinus Torvalds
12811da177e4SLinus Torvalds L2 = ((cbox_config >> 31) & 1 ? CSHAPE (size, 6, 1) : -1);
12821da177e4SLinus Torvalds #else
12831da177e4SLinus Torvalds L2 = external_cache_probe(512*1024, 6);
12841da177e4SLinus Torvalds #endif
12851da177e4SLinus Torvalds break;
12861da177e4SLinus Torvalds }
12871da177e4SLinus Torvalds
12881da177e4SLinus Torvalds case EV6_CPU:
12891da177e4SLinus Torvalds case EV67_CPU:
12901da177e4SLinus Torvalds case EV68CB_CPU:
12911da177e4SLinus Torvalds case EV68AL_CPU:
12921da177e4SLinus Torvalds case EV68CX_CPU:
12931da177e4SLinus Torvalds case EV69_CPU:
12941da177e4SLinus Torvalds L1I = L1D = CSHAPE(64*1024, 6, 2);
12951da177e4SLinus Torvalds L2 = external_cache_probe(1024*1024, 6);
12961da177e4SLinus Torvalds L3 = -1;
12971da177e4SLinus Torvalds break;
12981da177e4SLinus Torvalds
12991da177e4SLinus Torvalds case EV7_CPU:
13001da177e4SLinus Torvalds case EV79_CPU:
13011da177e4SLinus Torvalds L1I = L1D = CSHAPE(64*1024, 6, 2);
13021da177e4SLinus Torvalds L2 = CSHAPE(7*1024*1024/4, 6, 7);
13031da177e4SLinus Torvalds L3 = -1;
13041da177e4SLinus Torvalds break;
13051da177e4SLinus Torvalds
13061da177e4SLinus Torvalds default:
13071da177e4SLinus Torvalds /* Nothing known about this cpu type. */
13081da177e4SLinus Torvalds L1I = L1D = L2 = L3 = 0;
13091da177e4SLinus Torvalds break;
13101da177e4SLinus Torvalds }
13111da177e4SLinus Torvalds
13121da177e4SLinus Torvalds alpha_l1i_cacheshape = L1I;
13131da177e4SLinus Torvalds alpha_l1d_cacheshape = L1D;
13141da177e4SLinus Torvalds alpha_l2_cacheshape = L2;
13151da177e4SLinus Torvalds alpha_l3_cacheshape = L3;
13161da177e4SLinus Torvalds }
13171da177e4SLinus Torvalds
13181da177e4SLinus Torvalds /*
13191da177e4SLinus Torvalds * We show only CPU #0 info.
13201da177e4SLinus Torvalds */
13211da177e4SLinus Torvalds static void *
c_start(struct seq_file * f,loff_t * pos)13221da177e4SLinus Torvalds c_start(struct seq_file *f, loff_t *pos)
13231da177e4SLinus Torvalds {
13241da177e4SLinus Torvalds return *pos ? NULL : (char *)hwrpb + hwrpb->processor_offset;
13251da177e4SLinus Torvalds }
13261da177e4SLinus Torvalds
13271da177e4SLinus Torvalds static void *
c_next(struct seq_file * f,void * v,loff_t * pos)13281da177e4SLinus Torvalds c_next(struct seq_file *f, void *v, loff_t *pos)
13291da177e4SLinus Torvalds {
13307812193cSMatt Turner (*pos)++;
13311da177e4SLinus Torvalds return NULL;
13321da177e4SLinus Torvalds }
13331da177e4SLinus Torvalds
13341da177e4SLinus Torvalds static void
c_stop(struct seq_file * f,void * v)13351da177e4SLinus Torvalds c_stop(struct seq_file *f, void *v)
13361da177e4SLinus Torvalds {
13371da177e4SLinus Torvalds }
13381da177e4SLinus Torvalds
133903a44825SJan Engelhardt const struct seq_operations cpuinfo_op = {
13401da177e4SLinus Torvalds .start = c_start,
13411da177e4SLinus Torvalds .next = c_next,
13421da177e4SLinus Torvalds .stop = c_stop,
13431da177e4SLinus Torvalds .show = show_cpuinfo,
13441da177e4SLinus Torvalds };
13451da177e4SLinus Torvalds
13461da177e4SLinus Torvalds
13471da177e4SLinus Torvalds static int
alpha_panic_event(struct notifier_block * this,unsigned long event,void * ptr)13481da177e4SLinus Torvalds alpha_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
13491da177e4SLinus Torvalds {
13501da177e4SLinus Torvalds #if 1
13511da177e4SLinus Torvalds /* FIXME FIXME FIXME */
13521da177e4SLinus Torvalds /* If we are using SRM and serial console, just hard halt here. */
13531da177e4SLinus Torvalds if (alpha_using_srm && srmcons_output)
13541da177e4SLinus Torvalds __halt();
13551da177e4SLinus Torvalds #endif
13561da177e4SLinus Torvalds return NOTIFY_DONE;
13571da177e4SLinus Torvalds }
1358e5c6c8e4SMichael Neuling
add_pcspkr(void)1359e5c6c8e4SMichael Neuling static __init int add_pcspkr(void)
1360e5c6c8e4SMichael Neuling {
1361e5c6c8e4SMichael Neuling struct platform_device *pd;
1362e5c6c8e4SMichael Neuling int ret;
1363e5c6c8e4SMichael Neuling
1364e5c6c8e4SMichael Neuling pd = platform_device_alloc("pcspkr", -1);
1365e5c6c8e4SMichael Neuling if (!pd)
1366e5c6c8e4SMichael Neuling return -ENOMEM;
1367e5c6c8e4SMichael Neuling
1368e5c6c8e4SMichael Neuling ret = platform_device_add(pd);
1369e5c6c8e4SMichael Neuling if (ret)
1370e5c6c8e4SMichael Neuling platform_device_put(pd);
1371e5c6c8e4SMichael Neuling
1372e5c6c8e4SMichael Neuling return ret;
1373e5c6c8e4SMichael Neuling }
1374e5c6c8e4SMichael Neuling device_initcall(add_pcspkr);
1375