xref: /netbsd/sys/arch/sparc/sparc/cpuunit.c (revision 6550d01e)
1 /*	$NetBSD: cpuunit.c,v 1.13 2008/04/28 20:23:36 martin Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Autoconfiguration support for Sun4d "cpu units".
34  */
35 
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: cpuunit.c,v 1.13 2008/04/28 20:23:36 martin Exp $");
38 
39 #include <sys/param.h>
40 #include <sys/malloc.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 
44 #include <machine/autoconf.h>
45 #include <machine/bus.h>
46 
47 #include <sparc/sparc/cpuunitvar.h>
48 
49 struct cpuunit_softc {
50 	struct device sc_dev;
51 	int sc_node;				/* our OBP node */
52 
53 	bus_space_tag_t sc_st;			/* ours */
54 	bus_space_tag_t sc_bustag;		/* passed on to children */
55 
56 	int sc_device_id;			/* device-id */
57 	int sc_board;				/* board number */
58 };
59 
60 static int cpuunit_match(struct device *, struct cfdata *, void *);
61 static void cpuunit_attach(struct device *, struct device *, void *);
62 
63 CFATTACH_DECL(cpuunit, sizeof(struct cpuunit_softc),
64     cpuunit_match, cpuunit_attach, NULL, NULL);
65 
66 static int cpuunit_print(void *, const char *);
67 
68 static int cpuunit_setup_attach_args(struct cpuunit_softc *, bus_space_tag_t,
69     int, struct cpuunit_attach_args *);
70 static void cpuunit_destroy_attach_args(struct cpuunit_attach_args *);
71 
72 static int
73 cpuunit_match(struct device *parent, struct cfdata *cf, void *aux)
74 {
75 	struct mainbus_attach_args *ma = aux;
76 
77 	if (strcmp(ma->ma_name, "cpu-unit") == 0)
78 		return (1);
79 
80 	return (0);
81 }
82 
83 static void
84 cpuunit_attach(struct device *parent, struct device *self, void *aux)
85 {
86 	struct cpuunit_softc *sc = (void *) self;
87 	struct mainbus_attach_args *ma = aux;
88 	int node, error;
89 	bus_space_tag_t sbt;
90 
91 	sc->sc_node = ma->ma_node;
92 	sc->sc_st = ma->ma_bustag;
93 
94 	sc->sc_device_id = prom_getpropint(sc->sc_node, "device-id", -1);
95 	sc->sc_board = prom_getpropint(sc->sc_node, "board#", -1);
96 
97 	printf(": board #%d, ID %d\n", sc->sc_board, sc->sc_device_id);
98 
99 	/*
100 	 * Initialize the bus space tag we pass on to our children.
101 	 */
102 	sbt = sc->sc_bustag = malloc(sizeof(*sbt), M_DEVBUF, M_WAITOK);
103 	memcpy(sbt, sc->sc_st, sizeof(*sbt));
104 	sbt->cookie = sc;
105 	sbt->parent = sc->sc_st;
106 	sbt->nranges = 0;
107 	sbt->ranges = NULL;
108 
109 	/*
110 	 * Collect address translations from the OBP.
111 	 */
112 	error = prom_getprop(sc->sc_node, "ranges",
113 	    sizeof(struct openprom_range), &sbt->nranges, &sbt->ranges);
114 	if (error) {
115 		printf("%s: error %d getting \"ranges\" property\n",
116 		    sc->sc_dev.dv_xname, error);
117 		panic("cpuunit_attach");
118 	}
119 
120 	/* Attach the CPU (and possibly bootbus) child nodes. */
121 	for (node = firstchild(sc->sc_node); node != 0;
122 	     node = nextsibling(node)) {
123 		struct cpuunit_attach_args cpua;
124 
125 		if (cpuunit_setup_attach_args(sc, sbt, node, &cpua))
126 			panic("cpuunit_attach: failed to set up attach args");
127 
128 		(void) config_found(&sc->sc_dev, &cpua, cpuunit_print);
129 
130 		cpuunit_destroy_attach_args(&cpua);
131 	}
132 }
133 
134 static int
135 cpuunit_print(void *aux, const char *pnp)
136 {
137 	struct cpuunit_attach_args *cpua = aux;
138 
139 	if (pnp)
140 		aprint_normal("%s at %s", cpua->cpua_name, pnp);
141 
142 	return (UNCONF);
143 }
144 
145 static int
146 cpuunit_setup_attach_args(struct cpuunit_softc *sc, bus_space_tag_t bustag,
147     int node, struct cpuunit_attach_args *cpua)
148 {
149 	int n, error;
150 
151 	memset(cpua, 0, sizeof(*cpua));
152 
153 	error = prom_getprop(node, "name", 1, &n, &cpua->cpua_name);
154 	if (error)
155 		return (error);
156 	cpua->cpua_name[n] = '\0';
157 
158 	error = prom_getprop(node, "device_type", 1, &n,
159 	    &cpua->cpua_type);
160 	if (error) {
161 		free(cpua->cpua_name, M_DEVBUF);
162 		return (error);
163 	}
164 
165 	cpua->cpua_bustag = bustag;
166 	cpua->cpua_node = node;
167 	cpua->cpua_device_id = sc->sc_device_id;
168 
169 	return (0);
170 }
171 
172 static void
173 cpuunit_destroy_attach_args(struct cpuunit_attach_args *cpua)
174 {
175 
176 	if (cpua->cpua_name != NULL)
177 		free(cpua->cpua_name, M_DEVBUF);
178 
179 	if (cpua->cpua_type != NULL)
180 		free(cpua->cpua_type, M_DEVBUF);
181 }
182