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 extern void generic_find_legacy_serial_ports(u64 *physport,
75 		unsigned int *default_speed);
76 
77 static void maple_restart(char *cmd)
78 {
79 	unsigned int maple_nvram_base;
80 	unsigned int maple_nvram_offset;
81 	unsigned int maple_nvram_command;
82 	struct device_node *rtcs;
83 
84 	/* find NVRAM device */
85 	rtcs = find_compatible_devices("nvram", "AMD8111");
86 	if (rtcs && rtcs->addrs) {
87 		maple_nvram_base = rtcs->addrs[0].address;
88 	} else {
89 		printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
90 		printk(KERN_EMERG "Maple: Manual Restart Required\n");
91 		return;
92 	}
93 
94 	/* find service processor device */
95 	rtcs = find_devices("service-processor");
96 	if (!rtcs) {
97 		printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
98 		printk(KERN_EMERG "Maple: Manual Restart Required\n");
99 		return;
100 	}
101 	maple_nvram_offset = *(unsigned int*) get_property(rtcs,
102 			"restart-addr", NULL);
103 	maple_nvram_command = *(unsigned int*) get_property(rtcs,
104 			"restart-value", NULL);
105 
106 	/* send command */
107 	outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
108 	for (;;) ;
109 }
110 
111 static void maple_power_off(void)
112 {
113 	unsigned int maple_nvram_base;
114 	unsigned int maple_nvram_offset;
115 	unsigned int maple_nvram_command;
116 	struct device_node *rtcs;
117 
118 	/* find NVRAM device */
119 	rtcs = find_compatible_devices("nvram", "AMD8111");
120 	if (rtcs && rtcs->addrs) {
121 		maple_nvram_base = rtcs->addrs[0].address;
122 	} else {
123 		printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
124 		printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
125 		return;
126 	}
127 
128 	/* find service processor device */
129 	rtcs = find_devices("service-processor");
130 	if (!rtcs) {
131 		printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
132 		printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
133 		return;
134 	}
135 	maple_nvram_offset = *(unsigned int*) get_property(rtcs,
136 			"power-off-addr", NULL);
137 	maple_nvram_command = *(unsigned int*) get_property(rtcs,
138 			"power-off-value", NULL);
139 
140 	/* send command */
141 	outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
142 	for (;;) ;
143 }
144 
145 static void maple_halt(void)
146 {
147 	maple_power_off();
148 }
149 
150 #ifdef CONFIG_SMP
151 struct smp_ops_t maple_smp_ops = {
152 	.probe		= smp_mpic_probe,
153 	.message_pass	= smp_mpic_message_pass,
154 	.kick_cpu	= smp_generic_kick_cpu,
155 	.setup_cpu	= smp_mpic_setup_cpu,
156 	.give_timebase	= smp_generic_give_timebase,
157 	.take_timebase	= smp_generic_take_timebase,
158 };
159 #endif /* CONFIG_SMP */
160 
161 void __init maple_setup_arch(void)
162 {
163 	/* init to some ~sane value until calibrate_delay() runs */
164 	loops_per_jiffy = 50000000;
165 
166 	/* Setup SMP callback */
167 #ifdef CONFIG_SMP
168 	smp_ops = &maple_smp_ops;
169 #endif
170 	/* Lookup PCI hosts */
171        	maple_pci_init();
172 
173 #ifdef CONFIG_DUMMY_CONSOLE
174 	conswitchp = &dummy_con;
175 #endif
176 
177 	printk(KERN_INFO "Using native/NAP idle loop\n");
178 }
179 
180 /*
181  * Early initialization.
182  */
183 static void __init maple_init_early(void)
184 {
185 	unsigned int default_speed;
186 	u64 physport;
187 
188 	DBG(" -> maple_init_early\n");
189 
190 	/* Initialize hash table, from now on, we can take hash faults
191 	 * and call ioremap
192 	 */
193 	hpte_init_native();
194 
195 	/* Setup interrupt mapping options */
196 	ppc64_interrupt_controller = IC_OPEN_PIC;
197 
198 	iommu_init_early_dart();
199 
200 	DBG(" <- maple_init_early\n");
201 }
202 
203 
204 static __init void maple_init_IRQ(void)
205 {
206 	struct device_node *root;
207 	unsigned int *opprop;
208 	unsigned long opic_addr;
209 	struct mpic *mpic;
210 	unsigned char senses[128];
211 	int n;
212 
213 	DBG(" -> maple_init_IRQ\n");
214 
215 	/* XXX: Non standard, replace that with a proper openpic/mpic node
216 	 * in the device-tree. Find the Open PIC if present */
217 	root = of_find_node_by_path("/");
218 	opprop = (unsigned int *) get_property(root,
219 				"platform-open-pic", NULL);
220 	if (opprop == 0)
221 		panic("OpenPIC not found !\n");
222 
223 	n = prom_n_addr_cells(root);
224 	for (opic_addr = 0; n > 0; --n)
225 		opic_addr = (opic_addr << 32) + *opprop++;
226 	of_node_put(root);
227 
228 	/* Obtain sense values from device-tree */
229 	prom_get_irq_senses(senses, 0, 128);
230 
231 	mpic = mpic_alloc(opic_addr,
232 			  MPIC_PRIMARY | MPIC_BIG_ENDIAN |
233 			  MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
234 			  0, 0, 128, 128, senses, 128, "U3-MPIC");
235 	BUG_ON(mpic == NULL);
236 	mpic_init(mpic);
237 
238 	DBG(" <- maple_init_IRQ\n");
239 }
240 
241 static void __init maple_progress(char *s, unsigned short hex)
242 {
243 	printk("*** %04x : %s\n", hex, s ? s : "");
244 }
245 
246 
247 /*
248  * Called very early, MMU is off, device-tree isn't unflattened
249  */
250 static int __init maple_probe(int platform)
251 {
252 	if (platform != PLATFORM_MAPLE)
253 		return 0;
254 	/*
255 	 * On U3, the DART (iommu) must be allocated now since it
256 	 * has an impact on htab_initialize (due to the large page it
257 	 * occupies having to be broken up so the DART itself is not
258 	 * part of the cacheable linar mapping
259 	 */
260 	alloc_dart_table();
261 
262 	return 1;
263 }
264 
265 struct machdep_calls __initdata maple_md = {
266 	.probe			= maple_probe,
267 	.setup_arch		= maple_setup_arch,
268 	.init_early		= maple_init_early,
269 	.init_IRQ		= maple_init_IRQ,
270 	.get_irq		= mpic_get_irq,
271 	.pcibios_fixup		= maple_pcibios_fixup,
272 	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
273 	.restart		= maple_restart,
274 	.power_off		= maple_power_off,
275 	.halt			= maple_halt,
276        	.get_boot_time		= maple_get_boot_time,
277        	.set_rtc_time		= maple_set_rtc_time,
278        	.get_rtc_time		= maple_get_rtc_time,
279       	.calibrate_decr		= generic_calibrate_decr,
280 	.progress		= maple_progress,
281 	.idle_loop		= native_idle,
282 #ifdef CONFIG_KEXEC
283 	.machine_kexec		= default_machine_kexec,
284 	.machine_kexec_prepare	= default_machine_kexec_prepare,
285 	.machine_crash_shutdown	= default_machine_crash_shutdown,
286 #endif
287 };
288