xref: /netbsd-src/sys/arch/powerpc/booke/dev/cpunode.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: cpunode.c,v 1.5 2011/05/28 05:25:39 matt Exp $	*/
2 /*-
3  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to The NetBSD Foundation
7  * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8  * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9  *
10  * This material is based upon work supported by the Defense Advanced Research
11  * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12  * Contract No. N66001-09-C-2073.
13  * Approved for Public Release, Distribution Unlimited
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include <sys/cdefs.h>
38 
39 __KERNEL_RCSID(0, "$NetBSD: cpunode.c,v 1.5 2011/05/28 05:25:39 matt Exp $");
40 
41 #include <sys/param.h>
42 #include <sys/device.h>
43 #include <sys/cpu.h>
44 
45 #include "ioconf.h"
46 
47 #include <powerpc/booke/cpuvar.h>
48 
49 static int cpunode_match(device_t, cfdata_t, void *);
50 static void cpunode_attach(device_t, device_t, void *);
51 
52 CFATTACH_DECL_NEW(cpunode, sizeof(struct cpunode_softc),
53     cpunode_match, cpunode_attach, NULL, NULL);
54 
55 static u_int nodes;
56 
57 static int
58 cpunode_match(device_t parent, cfdata_t cf, void *aux)
59 {
60 	struct mainbus_attach_args * const ma = aux;
61 	if (strcmp(ma->ma_name, cpunode_cd.cd_name) != 0)
62 		return 0;
63 
64 	if (ma->ma_node > 8 || (nodes & (1 << ma->ma_node)))
65 		return 0;
66 
67 	return 1;
68 }
69 
70 static int
71 cpunode_print(void *aux, const char *pnp)
72 {
73 	struct cpunode_attach_args *cna = aux;
74 
75 	if (pnp)
76 #if 0
77 		return QUIET;
78 #else
79 		aprint_normal("%s at %s", cna->cna_locs.cnl_name, pnp);
80 #endif
81 
82 	if (cna->cna_locs.cnl_instance != 0)
83 		aprint_normal(" instance %d", cna->cna_locs.cnl_instance);
84 
85 	return UNCONF;
86 }
87 
88 static void
89 cpunode_attach(device_t parent, device_t self, void *aux)
90 {
91 	const struct cpunode_locators *cnl = cpu_md_ops.md_cpunode_locs;
92 	struct cpunode_softc * const sc = device_private(self);
93 	struct mainbus_attach_args * const ma = aux;
94 	struct cpunode_attach_args cna;
95 
96 	sc->sc_dev = self;
97 
98 	aprint_normal("\n");
99 	aprint_normal_dev(self,
100 	    "%"PRIu64"KB/%"PRIu64"B %"PRIu64"-banked %"PRIu64"-way unified L2 cache\n",
101 	    board_info_get_number("l2-cache-size") / 1024,
102 	    board_info_get_number("l2-cache-line-size"),
103 	    board_info_get_number("l2-cache-banks"),
104 	    board_info_get_number("l2-cache-ways"));
105 
106 	nodes |= 1 << ma->ma_node;
107 
108 	const uint16_t my_id = board_info_get_number("my-id");
109 
110 	for (u_int childmask = 1; cnl->cnl_name != NULL; cnl++) {
111 		bool inclusive = true;
112 		bool found = (cnl->cnl_ids[0] == 0);
113 
114 #if DEBUG > 1
115 		aprint_normal_dev(self, "dev=%s[%u], addr=%x@%x",
116 		    cnl->cnl_name, cnl->cnl_instance, cnl->cnl_size,
117 		    cnl->cnl_addr);
118 		if (cnl->cnl_nintr > 0) {
119 			aprint_normal(", intrs=%u", cnl->cnl_intrs[0]);
120 			for (u_int i = 1; i < cnl->cnl_nintr; i++)
121 				aprint_normal(",%u", cnl->cnl_intrs[i]);
122 		}
123 		aprint_normal("\n");
124 #endif
125 
126 		for (u_int i = 0;
127 		     !found
128 		     && i < __arraycount(cnl->cnl_ids)
129 		     && cnl->cnl_ids[i] != 0;
130 		     i++) {
131 			if (cnl->cnl_ids[i] == 0xffff) {
132 				inclusive = false;
133 				continue;
134 			}
135 			found = (cnl->cnl_ids[i] == my_id);
136 		}
137 		/*
138 		 * found & inclusive == match
139 		 * !found & !inclusive == match
140 		 * found & !inclusive == no match
141 		 * !found & inclusive == no match
142 		 * therefore
143 		 * found ^ inclusive = no match
144 		 * so
145 		 * !(found ^ inclusive) = match
146 		 */
147 		if (found ^ inclusive)
148 			continue;
149 
150 		cna.cna_busname = "cpunode";
151 		cna.cna_memt = ma->ma_memt;
152 		cna.cna_le_memt = ma->ma_le_memt;
153 		cna.cna_dmat = ma->ma_dmat;
154 		cna.cna_childmask = childmask;
155 		cna.cna_locs = *cnl;
156 
157 		(void)config_found_sm_loc(self, "cpunode", NULL, &cna,
158 		    cpunode_print, NULL);
159 		childmask <<= 1;
160 	}
161 	/*
162 	 * Anything MD left to do?
163 	 */
164 	if (cpu_md_ops.md_cpunode_attach != NULL)
165 		(*cpu_md_ops.md_cpunode_attach)(parent, self, aux);
166 }
167 
168 static int cpu_match(device_t, cfdata_t, void *);
169 static void cpu_attach(device_t, device_t, void *);
170 
171 CFATTACH_DECL_NEW(cpu, 0,
172     cpu_match, cpu_attach, NULL, NULL);
173 
174 static int
175 cpu_match(device_t parent, cfdata_t cf, void *aux)
176 {
177 	struct cpunode_softc * const psc = device_private(parent);
178 	struct cpunode_attach_args * const cna = aux;
179 
180 	if (strcmp(cna->cna_locs.cnl_name, cpu_cd.cd_name) != 0)
181 		return 0;
182 
183 	if (psc->sc_children & cna->cna_childmask)
184 		return 0;
185 
186 	return 1;
187 }
188 
189 static void
190 cpu_attach(device_t parent, device_t self, void *aux)
191 {
192 	struct cpunode_softc * const psc = device_private(parent);
193 	struct cpunode_attach_args * const cna = aux;
194 
195 	psc->sc_children |= cna->cna_childmask;
196 
197 	aprint_normal("\n");
198 
199 	(*cpu_md_ops.md_cpu_attach)(self, cna->cna_locs.cnl_instance);
200 }
201