Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Unmaintained SGI Visual Workstation support. | |
3 | * Split out from setup.c by davej@suse.de | |
4 | */ | |
5 | ||
6 | #include <linux/smp.h> | |
7 | #include <linux/init.h> | |
1da177e4 | 8 | #include <linux/interrupt.h> |
b5bd1cec | 9 | #include <linux/module.h> |
1da177e4 LT |
10 | |
11 | #include <asm/fixmap.h> | |
12 | #include <asm/arch_hooks.h> | |
13 | #include <asm/io.h> | |
e75eac33 JF |
14 | #include <asm/e820.h> |
15 | #include <asm/setup.h> | |
1da177e4 LT |
16 | #include "cobalt.h" |
17 | #include "piix4.h" | |
18 | ||
46bdac99 TD |
19 | int no_broadcast; |
20 | ||
1da177e4 LT |
21 | char visws_board_type = -1; |
22 | char visws_board_rev = -1; | |
23 | ||
24 | void __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 | ||
56 | outb_p(SIO_DEV_MSB, SIO_INDEX); | |
57 | outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */ | |
58 | ||
59 | outb_p(SIO_DEV_LSB, SIO_INDEX); | |
60 | outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */ | |
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 | ||
100 | void __init pre_intr_init_hook(void) | |
101 | { | |
102 | init_VISWS_APIC_irqs(); | |
103 | } | |
104 | ||
105 | void __init intr_init_hook(void) | |
106 | { | |
107 | #ifdef CONFIG_X86_LOCAL_APIC | |
108 | apic_intr_init(); | |
109 | #endif | |
110 | } | |
111 | ||
112 | void __init pre_setup_arch_hook() | |
113 | { | |
114 | visws_get_board_type_and_rev(); | |
115 | } | |
116 | ||
117 | static struct irqaction irq0 = { | |
118 | .handler = timer_interrupt, | |
b34942fe | 119 | .flags = IRQF_DISABLED | IRQF_IRQPOLL, |
1da177e4 LT |
120 | .name = "timer", |
121 | }; | |
122 | ||
123 | void __init time_init_hook(void) | |
124 | { | |
125 | printk(KERN_INFO "Starting Cobalt Timer system clock\n"); | |
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); | |
138 | } | |
e75eac33 JF |
139 | |
140 | /* Hook for machine specific memory setup. */ | |
141 | ||
142 | #define MB (1024 * 1024) | |
143 | ||
0686cd8f AB |
144 | unsigned long sgivwfb_mem_phys; |
145 | unsigned long sgivwfb_mem_size; | |
b5bd1cec RD |
146 | EXPORT_SYMBOL(sgivwfb_mem_phys); |
147 | EXPORT_SYMBOL(sgivwfb_mem_size); | |
e75eac33 JF |
148 | |
149 | long long mem_size __initdata = 0; | |
150 | ||
151 | char * __init machine_specific_memory_setup(void) | |
152 | { | |
153 | long long gfx_mem_size = 8 * MB; | |
154 | ||
30c82645 | 155 | mem_size = boot_params.alt_mem_k; |
e75eac33 JF |
156 | |
157 | if (!mem_size) { | |
158 | printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n"); | |
159 | mem_size = 128 * MB; | |
160 | } | |
161 | ||
162 | /* | |
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 | ||
172 | /* | |
173 | * Trim to nearest MB | |
174 | */ | |
175 | sgivwfb_mem_size &= ~((1 << 20) - 1); | |
176 | sgivwfb_mem_phys = mem_size - gfx_mem_size; | |
177 | ||
178 | add_memory_region(0, LOWMEMSIZE(), E820_RAM); | |
179 | add_memory_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM); | |
180 | add_memory_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED); | |
181 | ||
182 | return "PROM"; | |
e75eac33 | 183 | } |