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