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#include <asm/setup.h> 23 24#include "kernel.h" 25 26static char *cpu_mid_prop(void) 27{ 28 if (sparc_cpu_model == sun4d) 29 return "cpu-id"; 30 return "mid"; 31} 32 33static int check_cpu_node(phandle nd, int *cur_inst, 34 int (*compare)(phandle, int, void *), void *compare_arg, 35 phandle *prom_node, int *mid) 36{ 37 if (!compare(nd, *cur_inst, compare_arg)) { 38 if (prom_node) 39 *prom_node = nd; 40 if (mid) { 41 *mid = prom_getintdefault(nd, cpu_mid_prop(), 0); 42 if (sparc_cpu_model == sun4m) 43 *mid &= 3; 44 } 45 return 0; 46 } 47 48 (*cur_inst)++; 49 50 return -ENODEV; 51} 52 53static int __cpu_find_by(int (*compare)(phandle, int, void *), 54 void *compare_arg, phandle *prom_node, int *mid) 55{ 56 struct device_node *dp; 57 int cur_inst; 58 59 cur_inst = 0; 60 for_each_node_by_type(dp, "cpu") { 61 int err = check_cpu_node(dp->phandle, &cur_inst, 62 compare, compare_arg, 63 prom_node, mid); 64 if (!err) { 65 of_node_put(dp); 66 return 0; 67 } 68 } 69 70 return -ENODEV; 71} 72 73static int cpu_instance_compare(phandle nd, int instance, void *_arg) 74{ 75 int desired_instance = (int) _arg; 76 77 if (instance == desired_instance) 78 return 0; 79 return -ENODEV; 80} 81 82int cpu_find_by_instance(int instance, phandle *prom_node, int *mid) 83{ 84 return __cpu_find_by(cpu_instance_compare, (void *)instance, 85 prom_node, mid); 86} 87 88static int cpu_mid_compare(phandle nd, int instance, void *_arg) 89{ 90 int desired_mid = (int) _arg; 91 int this_mid; 92 93 this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0); 94 if (this_mid == desired_mid 95 || (sparc_cpu_model == sun4m && (this_mid & 3) == desired_mid)) 96 return 0; 97 return -ENODEV; 98} 99 100int cpu_find_by_mid(int mid, phandle *prom_node) 101{ 102 return __cpu_find_by(cpu_mid_compare, (void *)mid, 103 prom_node, NULL); 104} 105 106/* sun4m uses truncated mids since we base the cpuid on the ttable/irqset 107 * address (0-3). This gives us the true hardware mid, which might have 108 * some other bits set. On 4d hardware and software mids are the same. 109 */ 110int cpu_get_hwmid(phandle prom_node) 111{ 112 return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV); 113} 114 115void __init device_scan(void) 116{ 117 printk(KERN_NOTICE "Booting Linux...\n"); 118 119#ifndef CONFIG_SMP 120 { 121 phandle cpu_node; 122 int err; 123 err = cpu_find_by_instance(0, &cpu_node, NULL); 124 if (err) { 125 /* Probably a sun4e, Sun is trying to trick us ;-) */ 126 prom_printf("No cpu nodes, cannot continue\n"); 127 prom_halt(); 128 } 129 cpu_data(0).clock_tick = prom_getintdefault(cpu_node, 130 "clock-frequency", 131 0); 132 } 133#endif /* !CONFIG_SMP */ 134 135 auxio_probe(); 136 auxio_power_probe(); 137} 138