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 53 #ifdef DEBUG 54 #define DBG(fmt...) udbg_printf(fmt) 55 #else 56 #define DBG(fmt...) 57 #endif 58 59 void cell_show_cpuinfo(struct seq_file *m) 60 { 61 struct device_node *root; 62 const char *model = ""; 63 64 root = of_find_node_by_path("/"); 65 if (root) 66 model = get_property(root, "model", NULL); 67 seq_printf(m, "machine\t\t: CHRP %s\n", model); 68 of_node_put(root); 69 } 70 71 #ifdef CONFIG_SPARSEMEM 72 static int __init find_spu_node_id(struct device_node *spe) 73 { 74 unsigned int *id; 75 #ifdef CONFIG_NUMA 76 struct device_node *cpu; 77 cpu = spe->parent->parent; 78 id = (unsigned int *)get_property(cpu, "node-id", NULL); 79 #else 80 id = NULL; 81 #endif 82 return id ? *id : 0; 83 } 84 85 static void __init cell_spuprop_present(struct device_node *spe, 86 const char *prop, int early) 87 { 88 struct address_prop { 89 unsigned long address; 90 unsigned int len; 91 } __attribute__((packed)) *p; 92 int proplen; 93 94 unsigned long start_pfn, end_pfn, pfn; 95 int node_id; 96 97 p = (void*)get_property(spe, prop, &proplen); 98 WARN_ON(proplen != sizeof (*p)); 99 100 node_id = find_spu_node_id(spe); 101 102 start_pfn = p->address >> PAGE_SHIFT; 103 end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; 104 105 /* We need to call memory_present *before* the call to sparse_init, 106 but we can initialize the page structs only *after* that call. 107 Thus, we're being called twice. */ 108 if (early) 109 memory_present(node_id, start_pfn, end_pfn); 110 else { 111 /* As the pages backing SPU LS and I/O are outside the range 112 of regular memory, their page structs were not initialized 113 by free_area_init. Do it here instead. */ 114 for (pfn = start_pfn; pfn < end_pfn; pfn++) { 115 struct page *page = pfn_to_page(pfn); 116 set_page_links(page, ZONE_DMA, node_id, pfn); 117 set_page_count(page, 0); 118 reset_page_mapcount(page); 119 SetPageReserved(page); 120 INIT_LIST_HEAD(&page->lru); 121 } 122 } 123 } 124 125 static void __init cell_spumem_init(int early) 126 { 127 struct device_node *node; 128 for (node = of_find_node_by_type(NULL, "spe"); 129 node; node = of_find_node_by_type(node, "spe")) { 130 cell_spuprop_present(node, "local-store", early); 131 cell_spuprop_present(node, "problem", early); 132 cell_spuprop_present(node, "priv1", early); 133 cell_spuprop_present(node, "priv2", early); 134 } 135 } 136 #else 137 static void __init cell_spumem_init(int early) 138 { 139 } 140 #endif 141 142 static void cell_progress(char *s, unsigned short hex) 143 { 144 printk("*** %04x : %s\n", hex, s ? s : ""); 145 } 146 147 static void __init cell_setup_arch(void) 148 { 149 ppc_md.init_IRQ = iic_init_IRQ; 150 ppc_md.get_irq = iic_get_irq; 151 152 #ifdef CONFIG_SMP 153 smp_init_cell(); 154 #endif 155 156 /* init to some ~sane value until calibrate_delay() runs */ 157 loops_per_jiffy = 50000000; 158 159 if (ROOT_DEV == 0) { 160 printk("No ramdisk, default root is /dev/hda2\n"); 161 ROOT_DEV = Root_HDA2; 162 } 163 164 /* Find and initialize PCI host bridges */ 165 init_pci_config_tokens(); 166 find_and_init_phbs(); 167 spider_init_IRQ(); 168 #ifdef CONFIG_DUMMY_CONSOLE 169 conswitchp = &dummy_con; 170 #endif 171 172 mmio_nvram_init(); 173 174 cell_spumem_init(0); 175 } 176 177 /* 178 * Early initialization. Relocation is on but do not reference unbolted pages 179 */ 180 static void __init cell_init_early(void) 181 { 182 DBG(" -> cell_init_early()\n"); 183 184 hpte_init_native(); 185 186 cell_init_iommu(); 187 188 ppc64_interrupt_controller = IC_CELL_PIC; 189 190 cell_spumem_init(1); 191 192 DBG(" <- cell_init_early()\n"); 193 } 194 195 196 static int __init cell_probe(int platform) 197 { 198 if (platform != PLATFORM_CELL) 199 return 0; 200 201 return 1; 202 } 203 204 struct machdep_calls __initdata cell_md = { 205 .probe = cell_probe, 206 .setup_arch = cell_setup_arch, 207 .init_early = cell_init_early, 208 .show_cpuinfo = cell_show_cpuinfo, 209 .restart = rtas_restart, 210 .power_off = rtas_power_off, 211 .halt = rtas_halt, 212 .get_boot_time = rtas_get_boot_time, 213 .get_rtc_time = rtas_get_rtc_time, 214 .set_rtc_time = rtas_set_rtc_time, 215 .calibrate_decr = generic_calibrate_decr, 216 .progress = cell_progress, 217 #ifdef CONFIG_KEXEC 218 .machine_kexec = default_machine_kexec, 219 .machine_kexec_prepare = default_machine_kexec_prepare, 220 .machine_crash_shutdown = default_machine_crash_shutdown, 221 #endif 222 }; 223