Merge master.kernel.org:/home/rmk/linux-2.6-serial
[linux-2.6] / 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 char *cpu_mid_prop(void)
33 {
34         if (tlb_type == spitfire)
35                 return "upa-portid";
36         return "portid";
37 }
38
39 static int check_cpu_node(int nd, int *cur_inst,
40                           int (*compare)(int, int, void *), void *compare_arg,
41                           int *prom_node, int *mid)
42 {
43         char node_str[128];
44
45         prom_getstring(nd, "device_type", node_str, sizeof(node_str));
46         if (strcmp(node_str, "cpu"))
47                 return -ENODEV;
48
49         if (!compare(nd, *cur_inst, compare_arg)) {
50                 if (prom_node)
51                         *prom_node = nd;
52                 if (mid)
53                         *mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
54                 return 0;
55         }
56
57         (*cur_inst)++;
58
59         return -ENODEV;
60 }
61
62 static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
63                          int *prom_node, int *mid)
64 {
65         int nd, cur_inst, err;
66
67         nd = prom_root_node;
68         cur_inst = 0;
69
70         err = check_cpu_node(nd, &cur_inst,
71                              compare, compare_arg,
72                              prom_node, mid);
73         if (err == 0)
74                 return 0;
75
76         nd = prom_getchild(nd);
77         while ((nd = prom_getsibling(nd)) != 0) {
78                 err = check_cpu_node(nd, &cur_inst,
79                                      compare, compare_arg,
80                                      prom_node, mid);
81                 if (err == 0)
82                         return 0;
83         }
84
85         return -ENODEV;
86 }
87
88 static int cpu_instance_compare(int nd, int instance, void *_arg)
89 {
90         int desired_instance = (int) (long) _arg;
91
92         if (instance == desired_instance)
93                 return 0;
94         return -ENODEV;
95 }
96
97 int cpu_find_by_instance(int instance, int *prom_node, int *mid)
98 {
99         return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
100                              prom_node, mid);
101 }
102
103 static int cpu_mid_compare(int nd, int instance, void *_arg)
104 {
105         int desired_mid = (int) (long) _arg;
106         int this_mid;
107
108         this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
109         if (this_mid == desired_mid)
110                 return 0;
111         return -ENODEV;
112 }
113
114 int cpu_find_by_mid(int mid, int *prom_node)
115 {
116         return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
117                              prom_node, NULL);
118 }
119
120 void __init device_scan(void)
121 {
122         /* FIX ME FAST... -DaveM */
123         ioport_resource.end = 0xffffffffffffffffUL;
124
125         prom_printf("Booting Linux...\n");
126
127 #ifndef CONFIG_SMP
128         {
129                 int err, cpu_node;
130                 err = cpu_find_by_instance(0, &cpu_node, NULL);
131                 if (err) {
132                         prom_printf("No cpu nodes, cannot continue\n");
133                         prom_halt();
134                 }
135                 cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
136                                                             "clock-frequency",
137                                                             0);
138                 cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
139                                                              "dcache-size",
140                                                              16 * 1024);
141                 cpu_data(0).dcache_line_size =
142                         prom_getintdefault(cpu_node, "dcache-line-size", 32);
143                 cpu_data(0).icache_size = prom_getintdefault(cpu_node,
144                                                              "icache-size",
145                                                              16 * 1024);
146                 cpu_data(0).icache_line_size =
147                         prom_getintdefault(cpu_node, "icache-line-size", 32);
148                 cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
149                                                              "ecache-size",
150                                                              4 * 1024 * 1024);
151                 cpu_data(0).ecache_line_size =
152                         prom_getintdefault(cpu_node, "ecache-line-size", 64);
153                 printk("CPU[0]: Caches "
154                        "D[sz(%d):line_sz(%d)] "
155                        "I[sz(%d):line_sz(%d)] "
156                        "E[sz(%d):line_sz(%d)]\n",
157                        cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
158                        cpu_data(0).icache_size, cpu_data(0).icache_line_size,
159                        cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
160         }
161 #endif
162
163         central_probe();
164
165         cpu_probe();
166 }