Merge branch 'drm-forlinus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[linux-2.6] / arch / powerpc / platforms / maple / setup.c
1 /*
2  *  Maple (970 eval board) setup code
3  *
4  *  (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org),
5  *                     IBM Corp. 
6  *
7  *  This program is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU General Public License
9  *  as published by the Free Software Foundation; either version
10  *  2 of the License, or (at your option) any later version.
11  *
12  */
13
14 #define DEBUG
15
16 #include <linux/config.h>
17 #include <linux/init.h>
18 #include <linux/errno.h>
19 #include <linux/sched.h>
20 #include <linux/kernel.h>
21 #include <linux/mm.h>
22 #include <linux/stddef.h>
23 #include <linux/unistd.h>
24 #include <linux/ptrace.h>
25 #include <linux/slab.h>
26 #include <linux/user.h>
27 #include <linux/a.out.h>
28 #include <linux/tty.h>
29 #include <linux/string.h>
30 #include <linux/delay.h>
31 #include <linux/ioport.h>
32 #include <linux/major.h>
33 #include <linux/initrd.h>
34 #include <linux/vt_kern.h>
35 #include <linux/console.h>
36 #include <linux/ide.h>
37 #include <linux/pci.h>
38 #include <linux/adb.h>
39 #include <linux/cuda.h>
40 #include <linux/pmu.h>
41 #include <linux/irq.h>
42 #include <linux/seq_file.h>
43 #include <linux/root_dev.h>
44 #include <linux/serial.h>
45 #include <linux/smp.h>
46
47 #include <asm/processor.h>
48 #include <asm/sections.h>
49 #include <asm/prom.h>
50 #include <asm/system.h>
51 #include <asm/pgtable.h>
52 #include <asm/bitops.h>
53 #include <asm/io.h>
54 #include <asm/kexec.h>
55 #include <asm/pci-bridge.h>
56 #include <asm/iommu.h>
57 #include <asm/machdep.h>
58 #include <asm/dma.h>
59 #include <asm/cputable.h>
60 #include <asm/time.h>
61 #include <asm/of_device.h>
62 #include <asm/lmb.h>
63 #include <asm/mpic.h>
64 #include <asm/udbg.h>
65
66 #include "maple.h"
67
68 #ifdef DEBUG
69 #define DBG(fmt...) udbg_printf(fmt)
70 #else
71 #define DBG(fmt...)
72 #endif
73
74 static void maple_restart(char *cmd)
75 {
76         unsigned int maple_nvram_base;
77         unsigned int maple_nvram_offset;
78         unsigned int maple_nvram_command;
79         struct device_node *rtcs;
80
81         /* find NVRAM device */
82         rtcs = find_compatible_devices("nvram", "AMD8111");
83         if (rtcs && rtcs->addrs) {
84                 maple_nvram_base = rtcs->addrs[0].address;
85         } else {
86                 printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
87                 printk(KERN_EMERG "Maple: Manual Restart Required\n");
88                 return;
89         }
90
91         /* find service processor device */
92         rtcs = find_devices("service-processor");
93         if (!rtcs) {
94                 printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
95                 printk(KERN_EMERG "Maple: Manual Restart Required\n");
96                 return;
97         }
98         maple_nvram_offset = *(unsigned int*) get_property(rtcs,
99                         "restart-addr", NULL);
100         maple_nvram_command = *(unsigned int*) get_property(rtcs,
101                         "restart-value", NULL);
102
103         /* send command */
104         outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
105         for (;;) ;
106 }
107
108 static void maple_power_off(void)
109 {
110         unsigned int maple_nvram_base;
111         unsigned int maple_nvram_offset;
112         unsigned int maple_nvram_command;
113         struct device_node *rtcs;
114
115         /* find NVRAM device */
116         rtcs = find_compatible_devices("nvram", "AMD8111");
117         if (rtcs && rtcs->addrs) {
118                 maple_nvram_base = rtcs->addrs[0].address;
119         } else {
120                 printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
121                 printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
122                 return;
123         }
124
125         /* find service processor device */
126         rtcs = find_devices("service-processor");
127         if (!rtcs) {
128                 printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
129                 printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
130                 return;
131         }
132         maple_nvram_offset = *(unsigned int*) get_property(rtcs,
133                         "power-off-addr", NULL);
134         maple_nvram_command = *(unsigned int*) get_property(rtcs,
135                         "power-off-value", NULL);
136
137         /* send command */
138         outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
139         for (;;) ;
140 }
141
142 static void maple_halt(void)
143 {
144         maple_power_off();
145 }
146
147 #ifdef CONFIG_SMP
148 struct smp_ops_t maple_smp_ops = {
149         .probe          = smp_mpic_probe,
150         .message_pass   = smp_mpic_message_pass,
151         .kick_cpu       = smp_generic_kick_cpu,
152         .setup_cpu      = smp_mpic_setup_cpu,
153         .give_timebase  = smp_generic_give_timebase,
154         .take_timebase  = smp_generic_take_timebase,
155 };
156 #endif /* CONFIG_SMP */
157
158 void __init maple_setup_arch(void)
159 {
160         /* init to some ~sane value until calibrate_delay() runs */
161         loops_per_jiffy = 50000000;
162
163         /* Setup SMP callback */
164 #ifdef CONFIG_SMP
165         smp_ops = &maple_smp_ops;
166 #endif
167         /* Lookup PCI hosts */
168         maple_pci_init();
169
170 #ifdef CONFIG_DUMMY_CONSOLE
171         conswitchp = &dummy_con;
172 #endif
173
174         printk(KERN_INFO "Using native/NAP idle loop\n");
175 }
176
177 /* 
178  * Early initialization.
179  */
180 static void __init maple_init_early(void)
181 {
182         unsigned int default_speed;
183         u64 physport;
184
185         DBG(" -> maple_init_early\n");
186
187         /* Initialize hash table, from now on, we can take hash faults
188          * and call ioremap
189          */
190         hpte_init_native();
191
192         /* Setup interrupt mapping options */
193         ppc64_interrupt_controller = IC_OPEN_PIC;
194
195         iommu_init_early_dart();
196
197         DBG(" <- maple_init_early\n");
198 }
199
200
201 static __init void maple_init_IRQ(void)
202 {
203         struct device_node *root;
204         unsigned int *opprop;
205         unsigned long opic_addr;
206         struct mpic *mpic;
207         unsigned char senses[128];
208         int n;
209
210         DBG(" -> maple_init_IRQ\n");
211
212         /* XXX: Non standard, replace that with a proper openpic/mpic node
213          * in the device-tree. Find the Open PIC if present */
214         root = of_find_node_by_path("/");
215         opprop = (unsigned int *) get_property(root,
216                                 "platform-open-pic", NULL);
217         if (opprop == 0)
218                 panic("OpenPIC not found !\n");
219
220         n = prom_n_addr_cells(root);
221         for (opic_addr = 0; n > 0; --n)
222                 opic_addr = (opic_addr << 32) + *opprop++;
223         of_node_put(root);
224
225         /* Obtain sense values from device-tree */
226         prom_get_irq_senses(senses, 0, 128);
227
228         mpic = mpic_alloc(opic_addr,
229                           MPIC_PRIMARY | MPIC_BIG_ENDIAN |
230                           MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
231                           0, 0, 128, 128, senses, 128, "U3-MPIC");
232         BUG_ON(mpic == NULL);
233         mpic_init(mpic);
234
235         DBG(" <- maple_init_IRQ\n");
236 }
237
238 static void __init maple_progress(char *s, unsigned short hex)
239 {
240         printk("*** %04x : %s\n", hex, s ? s : "");
241 }
242
243
244 /*
245  * Called very early, MMU is off, device-tree isn't unflattened
246  */
247 static int __init maple_probe(int platform)
248 {
249         if (platform != PLATFORM_MAPLE)
250                 return 0;
251         /*
252          * On U3, the DART (iommu) must be allocated now since it
253          * has an impact on htab_initialize (due to the large page it
254          * occupies having to be broken up so the DART itself is not
255          * part of the cacheable linar mapping
256          */
257         alloc_dart_table();
258
259         return 1;
260 }
261
262 struct machdep_calls __initdata maple_md = {
263         .probe                  = maple_probe,
264         .setup_arch             = maple_setup_arch,
265         .init_early             = maple_init_early,
266         .init_IRQ               = maple_init_IRQ,
267         .get_irq                = mpic_get_irq,
268         .pcibios_fixup          = maple_pcibios_fixup,
269         .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
270         .restart                = maple_restart,
271         .power_off              = maple_power_off,
272         .halt                   = maple_halt,
273         .get_boot_time          = maple_get_boot_time,
274         .set_rtc_time           = maple_set_rtc_time,
275         .get_rtc_time           = maple_get_rtc_time,
276         .calibrate_decr         = generic_calibrate_decr,
277         .progress               = maple_progress,
278         .idle_loop              = native_idle,
279 #ifdef CONFIG_KEXEC
280         .machine_kexec          = default_machine_kexec,
281         .machine_kexec_prepare  = default_machine_kexec_prepare,
282         .machine_crash_shutdown = default_machine_crash_shutdown,
283 #endif
284 };