Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* devices.c: Initial scan of the prom device tree for important
0003  *        Sparc device nodes which we need to find.
0004  *
0005  * This is based on the sparc64 version, but sun4m doesn't always use
0006  * the hardware MIDs, so be careful.
0007  *
0008  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
0009  */
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/threads.h>
0013 #include <linux/string.h>
0014 #include <linux/init.h>
0015 #include <linux/errno.h>
0016 
0017 #include <asm/page.h>
0018 #include <asm/oplib.h>
0019 #include <asm/prom.h>
0020 #include <asm/smp.h>
0021 #include <asm/cpudata.h>
0022 #include <asm/cpu_type.h>
0023 #include <asm/setup.h>
0024 
0025 #include "kernel.h"
0026 
0027 static char *cpu_mid_prop(void)
0028 {
0029     if (sparc_cpu_model == sun4d)
0030         return "cpu-id";
0031     return "mid";
0032 }
0033 
0034 static int check_cpu_node(phandle nd, int *cur_inst,
0035         int (*compare)(phandle, int, void *), void *compare_arg,
0036         phandle *prom_node, int *mid)
0037 {
0038     if (!compare(nd, *cur_inst, compare_arg)) {
0039         if (prom_node)
0040             *prom_node = nd;
0041         if (mid) {
0042             *mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
0043             if (sparc_cpu_model == sun4m)
0044                 *mid &= 3;
0045         }
0046         return 0;
0047     }
0048 
0049     (*cur_inst)++;
0050 
0051     return -ENODEV;
0052 }
0053 
0054 static int __cpu_find_by(int (*compare)(phandle, int, void *),
0055         void *compare_arg, phandle *prom_node, int *mid)
0056 {
0057     struct device_node *dp;
0058     int cur_inst;
0059 
0060     cur_inst = 0;
0061     for_each_node_by_type(dp, "cpu") {
0062         int err = check_cpu_node(dp->phandle, &cur_inst,
0063                      compare, compare_arg,
0064                      prom_node, mid);
0065         if (!err) {
0066             of_node_put(dp);
0067             return 0;
0068         }
0069     }
0070 
0071     return -ENODEV;
0072 }
0073 
0074 static int cpu_instance_compare(phandle nd, int instance, void *_arg)
0075 {
0076     int desired_instance = (int) _arg;
0077 
0078     if (instance == desired_instance)
0079         return 0;
0080     return -ENODEV;
0081 }
0082 
0083 int cpu_find_by_instance(int instance, phandle *prom_node, int *mid)
0084 {
0085     return __cpu_find_by(cpu_instance_compare, (void *)instance,
0086                  prom_node, mid);
0087 }
0088 
0089 static int cpu_mid_compare(phandle nd, int instance, void *_arg)
0090 {
0091     int desired_mid = (int) _arg;
0092     int this_mid;
0093 
0094     this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
0095     if (this_mid == desired_mid
0096         || (sparc_cpu_model == sun4m && (this_mid & 3) == desired_mid))
0097         return 0;
0098     return -ENODEV;
0099 }
0100 
0101 int cpu_find_by_mid(int mid, phandle *prom_node)
0102 {
0103     return __cpu_find_by(cpu_mid_compare, (void *)mid,
0104                  prom_node, NULL);
0105 }
0106 
0107 /* sun4m uses truncated mids since we base the cpuid on the ttable/irqset
0108  * address (0-3).  This gives us the true hardware mid, which might have
0109  * some other bits set.  On 4d hardware and software mids are the same.
0110  */
0111 int cpu_get_hwmid(phandle prom_node)
0112 {
0113     return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV);
0114 }
0115 
0116 void __init device_scan(void)
0117 {
0118     printk(KERN_NOTICE "Booting Linux...\n");
0119 
0120 #ifndef CONFIG_SMP
0121     {
0122         phandle cpu_node;
0123         int err;
0124         err = cpu_find_by_instance(0, &cpu_node, NULL);
0125         if (err) {
0126             /* Probably a sun4e, Sun is trying to trick us ;-) */
0127             prom_printf("No cpu nodes, cannot continue\n");
0128             prom_halt();
0129         }
0130         cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
0131                                 "clock-frequency",
0132                                 0);
0133     }
0134 #endif /* !CONFIG_SMP */
0135 
0136     auxio_probe();
0137     auxio_power_probe();
0138 }