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