devices.c 3.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* devices.c: Initial scan of the prom device tree for important
 *	      Sparc device nodes which we need to find.
 *
 * This is based on the sparc64 version, but sun4m doesn't always use
 * the hardware MIDs, so be careful.
 *
 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
 */

#include <linux/kernel.h>
#include <linux/threads.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/errno.h>

#include <asm/page.h>
#include <asm/oplib.h>
18
#include <asm/prom.h>
L
Linus Torvalds 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/cpudata.h>

extern void cpu_probe(void);
extern void clock_stop_probe(void); /* tadpole.c */
extern void sun4c_probe_memerr_reg(void);

static char *cpu_mid_prop(void)
{
	if (sparc_cpu_model == sun4d)
		return "cpu-id";
	return "mid";
}

static int check_cpu_node(int nd, int *cur_inst,
			  int (*compare)(int, int, void *), void *compare_arg,
			  int *prom_node, int *mid)
{
	if (!compare(nd, *cur_inst, compare_arg)) {
		if (prom_node)
			*prom_node = nd;
		if (mid) {
			*mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
			if (sparc_cpu_model == sun4m)
				*mid &= 3;
		}
		return 0;
	}

	(*cur_inst)++;

	return -ENODEV;
}

static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
			 int *prom_node, int *mid)
{
57 58
	struct device_node *dp;
	int cur_inst;
L
Linus Torvalds 已提交
59 60

	cur_inst = 0;
61
	for_each_node_by_type(dp, "cpu") {
62
		int err = check_cpu_node(dp->phandle, &cur_inst,
63 64
					 compare, compare_arg,
					 prom_node, mid);
J
Julia Lawall 已提交
65 66
		if (!err) {
			of_node_put(dp);
L
Linus Torvalds 已提交
67
			return 0;
J
Julia Lawall 已提交
68
		}
L
Linus Torvalds 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
	}

	return -ENODEV;
}

static int cpu_instance_compare(int nd, int instance, void *_arg)
{
	int desired_instance = (int) _arg;

	if (instance == desired_instance)
		return 0;
	return -ENODEV;
}

int cpu_find_by_instance(int instance, int *prom_node, int *mid)
{
	return __cpu_find_by(cpu_instance_compare, (void *)instance,
			     prom_node, mid);
}

static int cpu_mid_compare(int nd, int instance, void *_arg)
{
	int desired_mid = (int) _arg;
	int this_mid;

	this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
	if (this_mid == desired_mid
	    || (sparc_cpu_model == sun4m && (this_mid & 3) == desired_mid))
		return 0;
	return -ENODEV;
}

int cpu_find_by_mid(int mid, int *prom_node)
{
	return __cpu_find_by(cpu_mid_compare, (void *)mid,
			     prom_node, NULL);
}

/* sun4m uses truncated mids since we base the cpuid on the ttable/irqset
 * address (0-3).  This gives us the true hardware mid, which might have
 * some other bits set.  On 4d hardware and software mids are the same.
 */
int cpu_get_hwmid(int prom_node)
{
	return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV);
}

void __init device_scan(void)
{
	prom_printf("Booting Linux...\n");

#ifndef CONFIG_SMP
	{
		int err, cpu_node;
		err = cpu_find_by_instance(0, &cpu_node, NULL);
		if (err) {
			/* Probably a sun4e, Sun is trying to trick us ;-) */
			prom_printf("No cpu nodes, cannot continue\n");
			prom_halt();
		}
		cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
							    "clock-frequency",
							    0);
	}
#endif /* !CONFIG_SMP */

	cpu_probe();
	{
		extern void auxio_probe(void);
		extern void auxio_power_probe(void);
		auxio_probe();
		auxio_power_probe();
	}
	clock_stop_probe();

A
Adrian Bunk 已提交
144
	if (ARCH_SUN4C)
L
Linus Torvalds 已提交
145 146
		sun4c_probe_memerr_reg();
}