1 /* devices.c: Initial scan of the prom device tree for important 2 * Sparc device nodes which we need to find. 3 * 4 * This is based on the sparc64 version, but sun4m doesn't always use 5 * the hardware MIDs, so be careful. 6 * 7 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/threads.h> 12 #include <linux/string.h> 13 #include <linux/init.h> 14 #include <linux/errno.h> 15 16 #include <asm/page.h> 17 #include <asm/oplib.h> 18 #include <asm/prom.h> 19 #include <asm/smp.h> 20 #include <asm/cpudata.h> 21 #include <asm/cpu_type.h> 22 23 extern void clock_stop_probe(void); /* tadpole.c */ 24 25 static char *cpu_mid_prop(void) 26 { 27 if (sparc_cpu_model == sun4d) 28 return "cpu-id"; 29 return "mid"; 30 } 31 32 static int check_cpu_node(phandle nd, int *cur_inst, 33 int (*compare)(phandle, int, void *), void *compare_arg, 34 phandle *prom_node, int *mid) 35 { 36 if (!compare(nd, *cur_inst, compare_arg)) { 37 if (prom_node) 38 *prom_node = nd; 39 if (mid) { 40 *mid = prom_getintdefault(nd, cpu_mid_prop(), 0); 41 if (sparc_cpu_model == sun4m) 42 *mid &= 3; 43 } 44 return 0; 45 } 46 47 (*cur_inst)++; 48 49 return -ENODEV; 50 } 51 52 static int __cpu_find_by(int (*compare)(phandle, int, void *), 53 void *compare_arg, phandle *prom_node, int *mid) 54 { 55 struct device_node *dp; 56 int cur_inst; 57 58 cur_inst = 0; 59 for_each_node_by_type(dp, "cpu") { 60 int err = check_cpu_node(dp->phandle, &cur_inst, 61 compare, compare_arg, 62 prom_node, mid); 63 if (!err) { 64 of_node_put(dp); 65 return 0; 66 } 67 } 68 69 return -ENODEV; 70 } 71 72 static int cpu_instance_compare(phandle nd, int instance, void *_arg) 73 { 74 int desired_instance = (int) _arg; 75 76 if (instance == desired_instance) 77 return 0; 78 return -ENODEV; 79 } 80 81 int cpu_find_by_instance(int instance, phandle *prom_node, int *mid) 82 { 83 return __cpu_find_by(cpu_instance_compare, (void *)instance, 84 prom_node, mid); 85 } 86 87 static int cpu_mid_compare(phandle nd, int instance, void *_arg) 88 { 89 int desired_mid = (int) _arg; 90 int this_mid; 91 92 this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0); 93 if (this_mid == desired_mid 94 || (sparc_cpu_model == sun4m && (this_mid & 3) == desired_mid)) 95 return 0; 96 return -ENODEV; 97 } 98 99 int cpu_find_by_mid(int mid, phandle *prom_node) 100 { 101 return __cpu_find_by(cpu_mid_compare, (void *)mid, 102 prom_node, NULL); 103 } 104 105 /* sun4m uses truncated mids since we base the cpuid on the ttable/irqset 106 * address (0-3). This gives us the true hardware mid, which might have 107 * some other bits set. On 4d hardware and software mids are the same. 108 */ 109 int cpu_get_hwmid(phandle prom_node) 110 { 111 return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV); 112 } 113 114 void __init device_scan(void) 115 { 116 printk(KERN_NOTICE "Booting Linux...\n"); 117 118 #ifndef CONFIG_SMP 119 { 120 phandle cpu_node; 121 int err; 122 err = cpu_find_by_instance(0, &cpu_node, NULL); 123 if (err) { 124 /* Probably a sun4e, Sun is trying to trick us ;-) */ 125 prom_printf("No cpu nodes, cannot continue\n"); 126 prom_halt(); 127 } 128 cpu_data(0).clock_tick = prom_getintdefault(cpu_node, 129 "clock-frequency", 130 0); 131 } 132 #endif /* !CONFIG_SMP */ 133 134 { 135 extern void auxio_probe(void); 136 extern void auxio_power_probe(void); 137 auxio_probe(); 138 auxio_power_probe(); 139 } 140 clock_stop_probe(); 141 } 142