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