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