blob: ac11d872ef7435c050068a7930b3dd94ae223b95 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* 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 */
27DEFINE_SPINLOCK(ns87303_lock);
28
29extern void cpu_probe(void);
30extern void central_probe(void);
31
David S. Miller4cce4b72006-02-09 20:46:22 -080032static const char *cpu_mid_prop(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033{
34 if (tlb_type == spitfire)
35 return "upa-portid";
36 return "portid";
37}
38
David S. Miller4cce4b72006-02-09 20:46:22 -080039static 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
Linus Torvalds1da177e2005-04-16 15:20:36 -070056static 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)
David S. Miller4cce4b72006-02-09 20:46:22 -080070 *mid = get_cpu_mid(nd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 return 0;
72 }
73
74 (*cur_inst)++;
75
76 return -ENODEV;
77}
78
79static 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
105static 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
114int 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
120static int cpu_mid_compare(int nd, int instance, void *_arg)
121{
122 int desired_mid = (int) (long) _arg;
123 int this_mid;
124
David S. Miller4cce4b72006-02-09 20:46:22 -0800125 this_mid = get_cpu_mid(nd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 if (this_mid == desired_mid)
127 return 0;
128 return -ENODEV;
129}
130
131int 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
137void __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);
David S. Miller80dc0d62005-09-26 00:32:17 -0700155 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 }
178#endif
179
180 central_probe();
181
182 cpu_probe();
183}