1 /* 2 * linux/arch/powerpc/platforms/cell/cell_setup.c 3 * 4 * Copyright (C) 1995 Linus Torvalds 5 * Adapted from 'alpha' version by Gary Thomas 6 * Modified by Cort Dougan (cort@cs.nmt.edu) 7 * Modified by PPC64 Team, IBM Corp 8 * Modified by Cell Team, IBM Deutschland Entwicklung GmbH 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 13 * 2 of the License, or (at your option) any later version. 14 */ 15 #undef DEBUG 16 17 #include <linux/config.h> 18 #include <linux/sched.h> 19 #include <linux/kernel.h> 20 #include <linux/mm.h> 21 #include <linux/stddef.h> 22 #include <linux/unistd.h> 23 #include <linux/slab.h> 24 #include <linux/user.h> 25 #include <linux/reboot.h> 26 #include <linux/init.h> 27 #include <linux/delay.h> 28 #include <linux/irq.h> 29 #include <linux/seq_file.h> 30 #include <linux/root_dev.h> 31 #include <linux/console.h> 32 33 #include <asm/mmu.h> 34 #include <asm/processor.h> 35 #include <asm/io.h> 36 #include <asm/kexec.h> 37 #include <asm/pgtable.h> 38 #include <asm/prom.h> 39 #include <asm/rtas.h> 40 #include <asm/pci-bridge.h> 41 #include <asm/iommu.h> 42 #include <asm/dma.h> 43 #include <asm/machdep.h> 44 #include <asm/time.h> 45 #include <asm/nvram.h> 46 #include <asm/cputable.h> 47 #include <asm/ppc-pci.h> 48 #include <asm/irq.h> 49 50 #include "interrupt.h" 51 #include "iommu.h" 52 #include "pervasive.h" 53 54 #ifdef DEBUG 55 #define DBG(fmt...) udbg_printf(fmt) 56 #else 57 #define DBG(fmt...) 58 #endif 59 60 void cell_show_cpuinfo(struct seq_file *m) 61 { 62 struct device_node *root; 63 const char *model = ""; 64 65 root = of_find_node_by_path("/"); 66 if (root) 67 model = get_property(root, "model", NULL); 68 seq_printf(m, "machine\t\t: CHRP %s\n", model); 69 of_node_put(root); 70 } 71 72 #ifdef CONFIG_SPARSEMEM 73 static int __init find_spu_node_id(struct device_node *spe) 74 { 75 unsigned int *id; 76 #ifdef CONFIG_NUMA 77 struct device_node *cpu; 78 cpu = spe->parent->parent; 79 id = (unsigned int *)get_property(cpu, "node-id", NULL); 80 #else 81 id = NULL; 82 #endif 83 return id ? *id : 0; 84 } 85 86 static void __init cell_spuprop_present(struct device_node *spe, 87 const char *prop, int early) 88 { 89 struct address_prop { 90 unsigned long address; 91 unsigned int len; 92 } __attribute__((packed)) *p; 93 int proplen; 94 95 unsigned long start_pfn, end_pfn, pfn; 96 int node_id; 97 98 p = (void*)get_property(spe, prop, &proplen); 99 WARN_ON(proplen != sizeof (*p)); 100 101 node_id = find_spu_node_id(spe); 102 103 start_pfn = p->address >> PAGE_SHIFT; 104 end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; 105 106 /* We need to call memory_present *before* the call to sparse_init, 107 but we can initialize the page structs only *after* that call. 108 Thus, we're being called twice. */ 109 if (early) 110 memory_present(node_id, start_pfn, end_pfn); 111 else { 112 /* As the pages backing SPU LS and I/O are outside the range 113 of regular memory, their page structs were not initialized 114 by free_area_init. Do it here instead. */ 115 for (pfn = start_pfn; pfn < end_pfn; pfn++) { 116 struct page *page = pfn_to_page(pfn); 117 set_page_links(page, ZONE_DMA, node_id, pfn); 118 set_page_count(page, 1); 119 reset_page_mapcount(page); 120 SetPageReserved(page); 121 INIT_LIST_HEAD(&page->lru); 122 } 123 } 124 } 125 126 static void __init cell_spumem_init(int early) 127 { 128 struct device_node *node; 129 for (node = of_find_node_by_type(NULL, "spe"); 130 node; node = of_find_node_by_type(node, "spe")) { 131 cell_spuprop_present(node, "local-store", early); 132 cell_spuprop_present(node, "problem", early); 133 cell_spuprop_present(node, "priv1", early); 134 cell_spuprop_present(node, "priv2", early); 135 } 136 } 137 #else 138 static void __init cell_spumem_init(int early) 139 { 140 } 141 #endif 142 143 static void cell_progress(char *s, unsigned short hex) 144 { 145 printk("*** %04x : %s\n", hex, s ? s : ""); 146 } 147 148 static void __init cell_setup_arch(void) 149 { 150 ppc_md.init_IRQ = iic_init_IRQ; 151 ppc_md.get_irq = iic_get_irq; 152 153 #ifdef CONFIG_SMP 154 smp_init_cell(); 155 #endif 156 157 /* init to some ~sane value until calibrate_delay() runs */ 158 loops_per_jiffy = 50000000; 159 160 if (ROOT_DEV == 0) { 161 printk("No ramdisk, default root is /dev/hda2\n"); 162 ROOT_DEV = Root_HDA2; 163 } 164 165 /* Find and initialize PCI host bridges */ 166 init_pci_config_tokens(); 167 find_and_init_phbs(); 168 spider_init_IRQ(); 169 cell_pervasive_init(); 170 #ifdef CONFIG_DUMMY_CONSOLE 171 conswitchp = &dummy_con; 172 #endif 173 174 mmio_nvram_init(); 175 176 cell_spumem_init(0); 177 } 178 179 /* 180 * Early initialization. Relocation is on but do not reference unbolted pages 181 */ 182 static void __init cell_init_early(void) 183 { 184 DBG(" -> cell_init_early()\n"); 185 186 hpte_init_native(); 187 188 cell_init_iommu(); 189 190 ppc64_interrupt_controller = IC_CELL_PIC; 191 192 cell_spumem_init(1); 193 194 DBG(" <- cell_init_early()\n"); 195 } 196 197 198 static int __init cell_probe(int platform) 199 { 200 if (platform != PLATFORM_CELL) 201 return 0; 202 203 return 1; 204 } 205 206 /* 207 * Cell has no legacy IO; anything calling this function has to 208 * fail or bad things will happen 209 */ 210 static int cell_check_legacy_ioport(unsigned int baseport) 211 { 212 return -ENODEV; 213 } 214 215 struct machdep_calls __initdata cell_md = { 216 .probe = cell_probe, 217 .setup_arch = cell_setup_arch, 218 .init_early = cell_init_early, 219 .show_cpuinfo = cell_show_cpuinfo, 220 .restart = rtas_restart, 221 .power_off = rtas_power_off, 222 .halt = rtas_halt, 223 .get_boot_time = rtas_get_boot_time, 224 .get_rtc_time = rtas_get_rtc_time, 225 .set_rtc_time = rtas_set_rtc_time, 226 .calibrate_decr = generic_calibrate_decr, 227 .check_legacy_ioport = cell_check_legacy_ioport, 228 .progress = cell_progress, 229 #ifdef CONFIG_KEXEC 230 .machine_kexec = default_machine_kexec, 231 .machine_kexec_prepare = default_machine_kexec_prepare, 232 .machine_crash_shutdown = default_machine_crash_shutdown, 233 #endif 234 }; 235