aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mach-visws/setup.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-10 10:29:28 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-10 12:55:32 -0400
commit22d5c67c5b0476e463ce4b632ba9ec3953d33a5f (patch)
tree2a0e19587aa081c48f3cbb60585d47ebc9c52294 /arch/x86/mach-visws/setup.c
parent3b33553badcde952adcf3b3ba5faae38d7d85071 (diff)
x86, VisWS: turn into generic arch, make VisWS boot on a regular PC
first step: make the VISWS subarch boot on a regular PC. We take various shortcuts for that. We copy the generic arch setup file over into the VISWS setup file. This is the only step that is not expected to boot on a real VISWS. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mach-visws/setup.c')
-rw-r--r--arch/x86/mach-visws/setup.c249
1 files changed, 105 insertions, 144 deletions
diff --git a/arch/x86/mach-visws/setup.c b/arch/x86/mach-visws/setup.c
index d67868ec9b7f..2f5e277686b8 100644
--- a/arch/x86/mach-visws/setup.c
+++ b/arch/x86/mach-visws/setup.c
@@ -1,183 +1,144 @@
1/* 1/*
2 * Unmaintained SGI Visual Workstation support. 2 * Machine specific setup for generic
3 * Split out from setup.c by davej@suse.de
4 */ 3 */
5 4
6#include <linux/smp.h> 5#include <linux/smp.h>
7#include <linux/init.h> 6#include <linux/init.h>
8#include <linux/interrupt.h> 7#include <linux/interrupt.h>
9#include <linux/module.h> 8#include <asm/acpi.h>
10
11#include <asm/fixmap.h>
12#include <asm/arch_hooks.h> 9#include <asm/arch_hooks.h>
13#include <asm/io.h>
14#include <asm/e820.h> 10#include <asm/e820.h>
15#include <asm/setup.h> 11#include <asm/setup.h>
16#include "cobalt.h"
17#include "piix4.h"
18
19int no_broadcast;
20
21char visws_board_type = -1;
22char visws_board_rev = -1;
23
24void __init visws_get_board_type_and_rev(void)
25{
26 int raw;
27
28 visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
29 >> PIIX_GPI_BD_SHIFT;
30 /*
31 * Get Board rev.
32 * First, we have to initialize the 307 part to allow us access
33 * to the GPIO registers. Let's map them at 0x0fc0 which is right
34 * after the PIIX4 PM section.
35 */
36 outb_p(SIO_DEV_SEL, SIO_INDEX);
37 outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */
38
39 outb_p(SIO_DEV_MSB, SIO_INDEX);
40 outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */
41
42 outb_p(SIO_DEV_LSB, SIO_INDEX);
43 outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */
44
45 outb_p(SIO_DEV_ENB, SIO_INDEX);
46 outb_p(1, SIO_DATA); /* Enable GPIO registers. */
47
48 /*
49 * Now, we have to map the power management section to write
50 * a bit which enables access to the GPIO registers.
51 * What lunatic came up with this shit?
52 */
53 outb_p(SIO_DEV_SEL, SIO_INDEX);
54 outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */
55 12
56 outb_p(SIO_DEV_MSB, SIO_INDEX); 13#ifdef CONFIG_HOTPLUG_CPU
57 outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */ 14#define DEFAULT_SEND_IPI (1)
58 15#else
59 outb_p(SIO_DEV_LSB, SIO_INDEX); 16#define DEFAULT_SEND_IPI (0)
60 outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */ 17#endif
61
62 outb_p(SIO_DEV_ENB, SIO_INDEX);
63 outb_p(1, SIO_DATA); /* Enable PM registers. */
64
65 /*
66 * Now, write the PM register which enables the GPIO registers.
67 */
68 outb_p(SIO_PM_FER2, SIO_PM_INDEX);
69 outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
70
71 /*
72 * Now, initialize the GPIO registers.
73 * We want them all to be inputs which is the
74 * power on default, so let's leave them alone.
75 * So, let's just read the board rev!
76 */
77 raw = inb_p(SIO_GP_DATA1);
78 raw &= 0x7f; /* 7 bits of valid board revision ID. */
79
80 if (visws_board_type == VISWS_320) {
81 if (raw < 0x6) {
82 visws_board_rev = 4;
83 } else if (raw < 0xc) {
84 visws_board_rev = 5;
85 } else {
86 visws_board_rev = 6;
87 }
88 } else if (visws_board_type == VISWS_540) {
89 visws_board_rev = 2;
90 } else {
91 visws_board_rev = raw;
92 }
93
94 printk(KERN_INFO "Silicon Graphics Visual Workstation %s (rev %d) detected\n",
95 (visws_board_type == VISWS_320 ? "320" :
96 (visws_board_type == VISWS_540 ? "540" :
97 "unknown")), visws_board_rev);
98}
99 18
19int no_broadcast=DEFAULT_SEND_IPI;
20
21/**
22 * pre_intr_init_hook - initialisation prior to setting up interrupt vectors
23 *
24 * Description:
25 * Perform any necessary interrupt initialisation prior to setting up
26 * the "ordinary" interrupt call gates. For legacy reasons, the ISA
27 * interrupts should be initialised here if the machine emulates a PC
28 * in any way.
29 **/
100void __init pre_intr_init_hook(void) 30void __init pre_intr_init_hook(void)
101{ 31{
102 init_VISWS_APIC_irqs(); 32 init_ISA_irqs();
103} 33}
104 34
35/*
36 * IRQ2 is cascade interrupt to second interrupt controller
37 */
38static struct irqaction irq2 = {
39 .handler = no_action,
40 .mask = CPU_MASK_NONE,
41 .name = "cascade",
42};
43
44/**
45 * intr_init_hook - post gate setup interrupt initialisation
46 *
47 * Description:
48 * Fill in any interrupts that may have been left out by the general
49 * init_IRQ() routine. interrupts having to do with the machine rather
50 * than the devices on the I/O bus (like APIC interrupts in intel MP
51 * systems) are started here.
52 **/
105void __init intr_init_hook(void) 53void __init intr_init_hook(void)
106{ 54{
107#ifdef CONFIG_X86_LOCAL_APIC 55#ifdef CONFIG_X86_LOCAL_APIC
108 apic_intr_init(); 56 apic_intr_init();
109#endif 57#endif
58
59 if (!acpi_ioapic)
60 setup_irq(2, &irq2);
61}
62
63/**
64 * pre_setup_arch_hook - hook called prior to any setup_arch() execution
65 *
66 * Description:
67 * generally used to activate any machine specific identification
68 * routines that may be needed before setup_arch() runs. On VISWS
69 * this is used to get the board revision and type.
70 **/
71void __init pre_setup_arch_hook(void)
72{
110} 73}
111 74
112void __init pre_setup_arch_hook() 75/**
76 * trap_init_hook - initialise system specific traps
77 *
78 * Description:
79 * Called as the final act of trap_init(). Used in VISWS to initialise
80 * the various board specific APIC traps.
81 **/
82void __init trap_init_hook(void)
113{ 83{
114 visws_get_board_type_and_rev();
115} 84}
116 85
117static struct irqaction irq0 = { 86static struct irqaction irq0 = {
118 .handler = timer_interrupt, 87 .handler = timer_interrupt,
119 .flags = IRQF_DISABLED | IRQF_IRQPOLL, 88 .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
120 .name = "timer", 89 .mask = CPU_MASK_NONE,
90 .name = "timer"
121}; 91};
122 92
93/**
94 * time_init_hook - do any specific initialisations for the system timer.
95 *
96 * Description:
97 * Must plug the system timer interrupt source at HZ into the IRQ listed
98 * in irq_vectors.h:TIMER_IRQ
99 **/
123void __init time_init_hook(void) 100void __init time_init_hook(void)
124{ 101{
125 printk(KERN_INFO "Starting Cobalt Timer system clock\n"); 102 irq0.mask = cpumask_of_cpu(0);
126
127 /* Set the countdown value */
128 co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
129
130 /* Start the timer */
131 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
132
133 /* Enable (unmask) the timer interrupt */
134 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
135
136 /* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
137 setup_irq(0, &irq0); 103 setup_irq(0, &irq0);
138} 104}
139 105
140/* Hook for machine specific memory setup. */ 106#ifdef CONFIG_MCA
141 107/**
142#define MB (1024 * 1024) 108 * mca_nmi_hook - hook into MCA specific NMI chain
143 109 *
144unsigned long sgivwfb_mem_phys; 110 * Description:
145unsigned long sgivwfb_mem_size; 111 * The MCA (Microchannel Architecture) has an NMI chain for NMI sources
146EXPORT_SYMBOL(sgivwfb_mem_phys); 112 * along the MCA bus. Use this to hook into that chain if you will need
147EXPORT_SYMBOL(sgivwfb_mem_size); 113 * it.
148 114 **/
149long long mem_size __initdata = 0; 115void mca_nmi_hook(void)
150
151char * __init machine_specific_memory_setup(void)
152{ 116{
153 long long gfx_mem_size = 8 * MB; 117 /* If I recall correctly, there's a whole bunch of other things that
118 * we can do to check for NMI problems, but that's all I know about
119 * at the moment.
120 */
154 121
155 mem_size = boot_params.alt_mem_k; 122 printk("NMI generated from unknown source!\n");
123}
124#endif
156 125
157 if (!mem_size) { 126static __init int no_ipi_broadcast(char *str)
158 printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n"); 127{
159 mem_size = 128 * MB; 128 get_option(&str, &no_broadcast);
160 } 129 printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
130 "IPI Broadcast");
131 return 1;
132}
161 133
162 /* 134__setup("no_ipi_broadcast=", no_ipi_broadcast);
163 * this hardcodes the graphics memory to 8 MB
164 * it really should be sized dynamically (or at least
165 * set as a boot param)
166 */
167 if (!sgivwfb_mem_size) {
168 printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n");
169 sgivwfb_mem_size = 8 * MB;
170 }
171 135
172 /* 136static int __init print_ipi_mode(void)
173 * Trim to nearest MB 137{
174 */ 138 printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
175 sgivwfb_mem_size &= ~((1 << 20) - 1); 139 "Shortcut");
176 sgivwfb_mem_phys = mem_size - gfx_mem_size; 140 return 0;
141}
177 142
178 e820_add_region(0, LOWMEMSIZE(), E820_RAM); 143late_initcall(print_ipi_mode);
179 e820_add_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM);
180 e820_add_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED);
181 144
182 return "PROM";
183}