ia64/linux-2.6.18-xen.hg

annotate arch/sparc64/kernel/devices.c @ 0:831230e53067

Import 2.6.18 from kernel.org tarball.
author Ian Campbell <ian.campbell@xensource.com>
date Wed Apr 11 14:15:44 2007 +0100 (2007-04-11)
parents
children
rev   line source
ian@0 1 /* devices.c: Initial scan of the prom device tree for important
ian@0 2 * Sparc device nodes which we need to find.
ian@0 3 *
ian@0 4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
ian@0 5 */
ian@0 6
ian@0 7 #include <linux/kernel.h>
ian@0 8 #include <linux/threads.h>
ian@0 9 #include <linux/init.h>
ian@0 10 #include <linux/ioport.h>
ian@0 11 #include <linux/string.h>
ian@0 12 #include <linux/spinlock.h>
ian@0 13 #include <linux/errno.h>
ian@0 14 #include <linux/bootmem.h>
ian@0 15
ian@0 16 #include <asm/page.h>
ian@0 17 #include <asm/oplib.h>
ian@0 18 #include <asm/system.h>
ian@0 19 #include <asm/smp.h>
ian@0 20 #include <asm/spitfire.h>
ian@0 21 #include <asm/timer.h>
ian@0 22 #include <asm/cpudata.h>
ian@0 23
ian@0 24 /* Used to synchronize acceses to NatSemi SUPER I/O chip configure
ian@0 25 * operations in asm/ns87303.h
ian@0 26 */
ian@0 27 DEFINE_SPINLOCK(ns87303_lock);
ian@0 28
ian@0 29 extern void cpu_probe(void);
ian@0 30 extern void central_probe(void);
ian@0 31
ian@0 32 static const char *cpu_mid_prop(void)
ian@0 33 {
ian@0 34 if (tlb_type == spitfire)
ian@0 35 return "upa-portid";
ian@0 36 return "portid";
ian@0 37 }
ian@0 38
ian@0 39 static int get_cpu_mid(struct device_node *dp)
ian@0 40 {
ian@0 41 struct property *prop;
ian@0 42
ian@0 43 if (tlb_type == hypervisor) {
ian@0 44 struct linux_prom64_registers *reg;
ian@0 45 int len;
ian@0 46
ian@0 47 prop = of_find_property(dp, "cpuid", &len);
ian@0 48 if (prop && len == 4)
ian@0 49 return *(int *) prop->value;
ian@0 50
ian@0 51 prop = of_find_property(dp, "reg", NULL);
ian@0 52 reg = prop->value;
ian@0 53 return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
ian@0 54 } else {
ian@0 55 const char *prop_name = cpu_mid_prop();
ian@0 56
ian@0 57 prop = of_find_property(dp, prop_name, NULL);
ian@0 58 if (prop)
ian@0 59 return *(int *) prop->value;
ian@0 60 return 0;
ian@0 61 }
ian@0 62 }
ian@0 63
ian@0 64 static int check_cpu_node(struct device_node *dp, int *cur_inst,
ian@0 65 int (*compare)(struct device_node *, int, void *),
ian@0 66 void *compare_arg,
ian@0 67 struct device_node **dev_node, int *mid)
ian@0 68 {
ian@0 69 if (!compare(dp, *cur_inst, compare_arg)) {
ian@0 70 if (dev_node)
ian@0 71 *dev_node = dp;
ian@0 72 if (mid)
ian@0 73 *mid = get_cpu_mid(dp);
ian@0 74 return 0;
ian@0 75 }
ian@0 76
ian@0 77 (*cur_inst)++;
ian@0 78
ian@0 79 return -ENODEV;
ian@0 80 }
ian@0 81
ian@0 82 static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
ian@0 83 void *compare_arg,
ian@0 84 struct device_node **dev_node, int *mid)
ian@0 85 {
ian@0 86 struct device_node *dp;
ian@0 87 int cur_inst;
ian@0 88
ian@0 89 cur_inst = 0;
ian@0 90 for_each_node_by_type(dp, "cpu") {
ian@0 91 int err = check_cpu_node(dp, &cur_inst,
ian@0 92 compare, compare_arg,
ian@0 93 dev_node, mid);
ian@0 94 if (err == 0)
ian@0 95 return 0;
ian@0 96 }
ian@0 97
ian@0 98 return -ENODEV;
ian@0 99 }
ian@0 100
ian@0 101 static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
ian@0 102 {
ian@0 103 int desired_instance = (int) (long) _arg;
ian@0 104
ian@0 105 if (instance == desired_instance)
ian@0 106 return 0;
ian@0 107 return -ENODEV;
ian@0 108 }
ian@0 109
ian@0 110 int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
ian@0 111 {
ian@0 112 return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
ian@0 113 dev_node, mid);
ian@0 114 }
ian@0 115
ian@0 116 static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
ian@0 117 {
ian@0 118 int desired_mid = (int) (long) _arg;
ian@0 119 int this_mid;
ian@0 120
ian@0 121 this_mid = get_cpu_mid(dp);
ian@0 122 if (this_mid == desired_mid)
ian@0 123 return 0;
ian@0 124 return -ENODEV;
ian@0 125 }
ian@0 126
ian@0 127 int cpu_find_by_mid(int mid, struct device_node **dev_node)
ian@0 128 {
ian@0 129 return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
ian@0 130 dev_node, NULL);
ian@0 131 }
ian@0 132
ian@0 133 void __init device_scan(void)
ian@0 134 {
ian@0 135 /* FIX ME FAST... -DaveM */
ian@0 136 ioport_resource.end = 0xffffffffffffffffUL;
ian@0 137
ian@0 138 prom_printf("Booting Linux...\n");
ian@0 139
ian@0 140 #ifndef CONFIG_SMP
ian@0 141 {
ian@0 142 struct device_node *dp;
ian@0 143 int err, def;
ian@0 144
ian@0 145 err = cpu_find_by_instance(0, &dp, NULL);
ian@0 146 if (err) {
ian@0 147 prom_printf("No cpu nodes, cannot continue\n");
ian@0 148 prom_halt();
ian@0 149 }
ian@0 150 cpu_data(0).clock_tick =
ian@0 151 of_getintprop_default(dp, "clock-frequency", 0);
ian@0 152
ian@0 153 def = ((tlb_type == hypervisor) ?
ian@0 154 (8 * 1024) :
ian@0 155 (16 * 1024));
ian@0 156 cpu_data(0).dcache_size = of_getintprop_default(dp,
ian@0 157 "dcache-size",
ian@0 158 def);
ian@0 159
ian@0 160 def = 32;
ian@0 161 cpu_data(0).dcache_line_size =
ian@0 162 of_getintprop_default(dp, "dcache-line-size", def);
ian@0 163
ian@0 164 def = 16 * 1024;
ian@0 165 cpu_data(0).icache_size = of_getintprop_default(dp,
ian@0 166 "icache-size",
ian@0 167 def);
ian@0 168
ian@0 169 def = 32;
ian@0 170 cpu_data(0).icache_line_size =
ian@0 171 of_getintprop_default(dp, "icache-line-size", def);
ian@0 172
ian@0 173 def = ((tlb_type == hypervisor) ?
ian@0 174 (3 * 1024 * 1024) :
ian@0 175 (4 * 1024 * 1024));
ian@0 176 cpu_data(0).ecache_size = of_getintprop_default(dp,
ian@0 177 "ecache-size",
ian@0 178 def);
ian@0 179
ian@0 180 def = 64;
ian@0 181 cpu_data(0).ecache_line_size =
ian@0 182 of_getintprop_default(dp, "ecache-line-size", def);
ian@0 183 printk("CPU[0]: Caches "
ian@0 184 "D[sz(%d):line_sz(%d)] "
ian@0 185 "I[sz(%d):line_sz(%d)] "
ian@0 186 "E[sz(%d):line_sz(%d)]\n",
ian@0 187 cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
ian@0 188 cpu_data(0).icache_size, cpu_data(0).icache_line_size,
ian@0 189 cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
ian@0 190 }
ian@0 191 #endif
ian@0 192
ian@0 193 central_probe();
ian@0 194
ian@0 195 cpu_probe();
ian@0 196 }