xref: /titanic_44/usr/src/uts/sun4u/chicago/os/chicago.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/sysmacros.h>
32 #include <sys/sunddi.h>
33 #include <sys/esunddi.h>
34 #include <sys/platform_module.h>
35 #include <sys/errno.h>
36 #include <sys/lgrp.h>
37 #include <sys/memnode.h>
38 #include <sys/promif.h>
39 
40 #define	SHARED_MI2CV_PATH "/i2c@1f,520000"
41 static dev_info_t *shared_mi2cv_dip;
42 static kmutex_t chicago_mi2cv_mutex;
43 
44 int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
45 
46 void
47 startup_platform(void)
48 {
49 	mutex_init(&chicago_mi2cv_mutex, NULL, NULL, NULL);
50 }
51 
52 int
53 set_platform_tsb_spares()
54 {
55 	return (0);
56 }
57 
58 void
59 set_platform_defaults(void)
60 {
61 	extern char *tod_module_name;
62 	/* Set appropriate tod module for Chicago */
63 	if (tod_module_name == NULL)
64 		tod_module_name = "todds1337";
65 }
66 
67 /*
68  * Definitions for accessing the pci config space of the isa node
69  * of Southbridge.
70  */
71 static ddi_acc_handle_t isa_handle = NULL;	/* handle for isa pci space */
72 
73 
74 void
75 load_platform_drivers(void)
76 {
77 	/*
78 	 * Install power driver which handles the power button.
79 	 */
80 	if (i_ddi_attach_hw_nodes("power") != DDI_SUCCESS)
81 		cmn_err(CE_WARN, "Failed to install \"power\" driver.");
82 	(void) ddi_hold_driver(ddi_name_to_major("power"));
83 
84 	/*
85 	 * It is OK to return error because 'us' driver is not available
86 	 * in all clusters (e.g. missing in Core cluster).
87 	 */
88 	(void) i_ddi_attach_hw_nodes("us");
89 
90 	if (i_ddi_attach_hw_nodes("grbeep") != DDI_SUCCESS)
91 		cmn_err(CE_WARN, "Failed to install \"beep\" driver.");
92 
93 
94 	/*
95 	 * mc-us3i must stay loaded for plat_get_mem_unum()
96 	 */
97 	if (i_ddi_attach_hw_nodes("mc-us3i") != DDI_SUCCESS)
98 		cmn_err(CE_WARN, "mc-us3i driver failed to install");
99 	(void) ddi_hold_driver(ddi_name_to_major("mc-us3i"));
100 
101 	/*
102 	 * Figure out which mi2cv dip is shared with OBP for the nvram
103 	 * device, so the lock can be acquired.
104 	 */
105 	shared_mi2cv_dip = e_ddi_hold_devi_by_path(SHARED_MI2CV_PATH, 0);
106 
107 	/*
108 	 * todds1337 needs early attach
109 	 */
110 	if (i_ddi_attach_hw_nodes("todds1337") != DDI_SUCCESS)
111 		cmn_err(CE_WARN, "todds1337 driver failed to install");
112 }
113 
114 /*
115  * This routine is needed if a device error or timeout occurs before the
116  * driver is loaded.
117  */
118 /*ARGSUSED*/
119 int
120 plat_ide_chipreset(dev_info_t *dip, int chno)
121 {
122 	int	ret = DDI_SUCCESS;
123 
124 	if (isa_handle == NULL) {
125 		return (DDI_FAILURE);
126 	}
127 
128 	/*
129 	 * This will be filled in with the reset logic
130 	 * for the ULI1573 when that becomes available.
131 	 * currently this is just a stub.
132 	 */
133 	return (ret);
134 }
135 
136 
137 /*ARGSUSED*/
138 int
139 plat_cpu_poweron(struct cpu *cp)
140 {
141 	return (ENOTSUP);	/* not supported on this platform */
142 }
143 
144 /*ARGSUSED*/
145 int
146 plat_cpu_poweroff(struct cpu *cp)
147 {
148 	return (ENOTSUP);	/* not supported on this platform */
149 }
150 
151 /*ARGSUSED*/
152 void
153 plat_freelist_process(int mnode)
154 {
155 }
156 
157 char *platform_module_list[] = {
158 	"mi2cv",
159 	"jbusppm",
160 	"pca9556",
161 	"ppm",
162 	(char *)0
163 };
164 
165 /*ARGSUSED*/
166 void
167 plat_tod_fault(enum tod_fault_type tod_bad)
168 {
169 }
170 
171 /*ARGSUSED*/
172 int
173 plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
174     int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
175 {
176 	if (flt_in_memory && (p2get_mem_unum != NULL))
177 		return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
178 		    buf, buflen, lenp));
179 	else
180 		return (ENOTSUP);
181 }
182 
183 /*ARGSUSED*/
184 int
185 plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
186 {
187 	if (snprintf(buf, buflen, "MB") >= buflen) {
188 		return (ENOSPC);
189 	} else {
190 		*lenp = strlen(buf);
191 		return (0);
192 	}
193 }
194 
195 /*
196  * Fiesta support for lgroups.
197  *
198  * On fiesta platform, an lgroup platform handle == CPU id
199  */
200 
201 /*
202  * Macro for extracting the CPU number from the CPU id
203  */
204 #define	CPUID_TO_LGRP(id)	((id) & 0x7)
205 #define	CHICAGO_MC_SHIFT	36
206 
207 /*
208  * Return the platform handle for the lgroup containing the given CPU
209  */
210 void *
211 plat_lgrp_cpu_to_hand(processorid_t id)
212 {
213 	return ((void *) CPUID_TO_LGRP(id));
214 }
215 
216 /*
217  * Platform specific lgroup initialization
218  */
219 void
220 plat_lgrp_init(void)
221 {
222 	dnode_t		curnode;
223 	char		tmp_name[MAXSYSNAME];
224 	int		portid;
225 	int		cpucnt = 0;
226 	int		max_portid = -1;
227 	extern uint32_t lgrp_expand_proc_thresh;
228 	extern uint32_t lgrp_expand_proc_diff;
229 	extern pgcnt_t	lgrp_mem_free_thresh;
230 	extern uint32_t lgrp_loadavg_tolerance;
231 	extern uint32_t lgrp_loadavg_max_effect;
232 	extern uint32_t lgrp_load_thresh;
233 	extern lgrp_mem_policy_t  lgrp_mem_policy_root;
234 
235 	/*
236 	 * Count the number of CPUs installed to determine if
237 	 * NUMA optimization should be enabled or not.
238 	 *
239 	 * All CPU nodes reside in the root node and have a
240 	 * device type "cpu".
241 	 */
242 	curnode = prom_rootnode();
243 	for (curnode = prom_childnode(curnode); curnode;
244 	    curnode = prom_nextnode(curnode)) {
245 		bzero(tmp_name, MAXSYSNAME);
246 		if (prom_getproplen(curnode, OBP_NAME) < MAXSYSNAME) {
247 			if (prom_getprop(curnode, OBP_NAME,
248 			    (caddr_t)tmp_name) == -1 || prom_getprop(curnode,
249 			    OBP_DEVICETYPE, tmp_name) == -1 || strcmp(tmp_name,
250 			    "cpu") != 0)
251 			continue;
252 
253 			cpucnt++;
254 			if (prom_getprop(curnode, "portid", (caddr_t)&portid) !=
255 			    -1 && portid > max_portid)
256 				max_portid = portid;
257 		}
258 	}
259 	if (cpucnt <= 1)
260 		max_mem_nodes = 1;
261 	else if (max_portid >= 0 && max_portid < MAX_MEM_NODES)
262 		max_mem_nodes = max_portid + 1;
263 
264 	/*
265 	 * Set tuneables for fiesta architecture
266 	 *
267 	 * lgrp_expand_proc_thresh is the minimum load on the lgroups
268 	 * this process is currently running on before considering
269 	 * expanding threads to another lgroup.
270 	 *
271 	 * lgrp_expand_proc_diff determines how much less the remote lgroup
272 	 * must be loaded before expanding to it.
273 	 *
274 	 * Optimize for memory bandwidth by spreading multi-threaded
275 	 * program to different lgroups.
276 	 */
277 	lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1;
278 	lgrp_expand_proc_diff = lgrp_loadavg_max_effect / 2;
279 	lgrp_loadavg_tolerance = lgrp_loadavg_max_effect / 2;
280 	lgrp_mem_free_thresh = 1;	/* home lgrp must have some memory */
281 	lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1;
282 	lgrp_mem_policy_root = LGRP_MEM_POLICY_NEXT;
283 	lgrp_load_thresh = 0;
284 
285 	mem_node_pfn_shift = CHICAGO_MC_SHIFT - MMU_PAGESHIFT;
286 }
287 
288 /*
289  * Return latency between "from" and "to" lgroups
290  *
291  * This latency number can only be used for relative comparison
292  * between lgroups on the running system, cannot be used across platforms,
293  * and may not reflect the actual latency.  It is platform and implementation
294  * specific, so platform gets to decide its value.  It would be nice if the
295  * number was at least proportional to make comparisons more meaningful though.
296  * NOTE: The numbers below are supposed to be load latencies for uncached
297  * memory divided by 10.
298  */
299 int
300 plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to)
301 {
302 	/*
303 	 * Return remote latency when there are more than two lgroups
304 	 * (root and child) and getting latency between two different
305 	 * lgroups or root is involved
306 	 */
307 	if (lgrp_optimizations() && (from != to ||
308 	    from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE))
309 		return (17);
310 	else
311 		return (12);
312 }
313 
314 int
315 plat_pfn_to_mem_node(pfn_t pfn)
316 {
317 	ASSERT(max_mem_nodes > 1);
318 	return (pfn >> mem_node_pfn_shift);
319 }
320 
321 /*
322  * Assign memnode to lgroups
323  */
324 void
325 plat_fill_mc(dnode_t nodeid)
326 {
327 	int		portid;
328 
329 	/*
330 	 * Chicago memory controller portid == global CPU id
331 	 */
332 	if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) == -1) ||
333 	    (portid < 0))
334 		return;
335 
336 	if (portid < max_mem_nodes)
337 		plat_assign_lgrphand_to_mem_node((lgrp_handle_t)portid, portid);
338 }
339 
340 /* ARGSUSED */
341 void
342 plat_build_mem_nodes(u_longlong_t *list, size_t nelems)
343 {
344 	size_t	elem;
345 	pfn_t	basepfn;
346 	pgcnt_t	npgs;
347 
348 	/*
349 	 * Boot install lists are arranged <addr, len>, <addr, len>, ...
350 	 */
351 	for (elem = 0; elem < nelems; elem += 2) {
352 		basepfn = btop(list[elem]);
353 		npgs = btop(list[elem+1]);
354 		mem_node_add_slice(basepfn, basepfn + npgs - 1);
355 	}
356 }
357 
358 /*
359  * Common locking enter code
360  */
361 void
362 plat_setprop_enter(void)
363 {
364 	mutex_enter(&chicago_mi2cv_mutex);
365 }
366 
367 /*
368  * Common locking exit code
369  */
370 void
371 plat_setprop_exit(void)
372 {
373 	mutex_exit(&chicago_mi2cv_mutex);
374 }
375 
376 /*
377  * Called by mi2cv driver
378  */
379 void
380 plat_shared_i2c_enter(dev_info_t *i2cnexus_dip)
381 {
382 	if (i2cnexus_dip == shared_mi2cv_dip) {
383 		plat_setprop_enter();
384 	}
385 }
386 
387 /*
388  * Called by mi2cv driver
389  */
390 void
391 plat_shared_i2c_exit(dev_info_t *i2cnexus_dip)
392 {
393 	if (i2cnexus_dip == shared_mi2cv_dip) {
394 		plat_setprop_exit();
395 	}
396 }
397