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