xref: /linux-6.15/arch/alpha/kernel/setup.c (revision 430ad3f0)
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