11121Sjroberts /*
21121Sjroberts * CDDL HEADER START
31121Sjroberts *
41121Sjroberts * The contents of this file are subject to the terms of the
51121Sjroberts * Common Development and Distribution License (the "License").
61121Sjroberts * You may not use this file except in compliance with the License.
71121Sjroberts *
81121Sjroberts * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91121Sjroberts * or http://www.opensolaris.org/os/licensing.
101121Sjroberts * See the License for the specific language governing permissions
111121Sjroberts * and limitations under the License.
121121Sjroberts *
131121Sjroberts * When distributing Covered Code, include this CDDL HEADER in each
141121Sjroberts * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151121Sjroberts * If applicable, add the following below this CDDL HEADER, with the
161121Sjroberts * fields enclosed by brackets "[]" replaced with your own identifying
171121Sjroberts * information: Portions Copyright [yyyy] [name of copyright owner]
181121Sjroberts *
191121Sjroberts * CDDL HEADER END
201121Sjroberts */
211121Sjroberts
22920Sjbeloro /*
23*11311SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24920Sjbeloro * Use is subject to license terms.
25920Sjbeloro */
26920Sjbeloro
27920Sjbeloro #include <sys/param.h>
28920Sjbeloro #include <sys/systm.h>
29920Sjbeloro #include <sys/sysmacros.h>
30920Sjbeloro #include <sys/sunddi.h>
31920Sjbeloro #include <sys/esunddi.h>
32920Sjbeloro
33920Sjbeloro #include <sys/platform_module.h>
34920Sjbeloro #include <sys/errno.h>
35920Sjbeloro #include <sys/cpu_sgnblk_defs.h>
36920Sjbeloro #include <sys/rmc_comm_dp.h>
37920Sjbeloro #include <sys/rmc_comm_drvintf.h>
38920Sjbeloro #include <sys/modctl.h>
39920Sjbeloro #include <sys/lgrp.h>
40920Sjbeloro #include <sys/memnode.h>
41920Sjbeloro #include <sys/promif.h>
42920Sjbeloro
43920Sjbeloro #define SHARED_MI2CV_PATH "/i2c@1f,520000"
44920Sjbeloro static dev_info_t *shared_mi2cv_dip;
45920Sjbeloro static kmutex_t mi2cv_mutex;
46920Sjbeloro
47920Sjbeloro int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
48920Sjbeloro static void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int);
49920Sjbeloro int (*rmc_req_now)(rmc_comm_msg_t *, uint8_t) = NULL;
50920Sjbeloro
51920Sjbeloro void
startup_platform(void)52920Sjbeloro startup_platform(void)
53920Sjbeloro {
54920Sjbeloro mutex_init(&mi2cv_mutex, NULL, NULL, NULL);
55920Sjbeloro }
56920Sjbeloro
57920Sjbeloro int
set_platform_tsb_spares()58920Sjbeloro set_platform_tsb_spares()
59920Sjbeloro {
60920Sjbeloro return (0);
61920Sjbeloro }
62920Sjbeloro
63920Sjbeloro void
set_platform_defaults(void)64920Sjbeloro set_platform_defaults(void)
65920Sjbeloro {
66920Sjbeloro extern char *tod_module_name;
67920Sjbeloro /* Set appropriate tod module */
68920Sjbeloro if (tod_module_name == NULL)
69920Sjbeloro tod_module_name = "todm5823";
70920Sjbeloro
71920Sjbeloro cpu_sgn_func = cpu_sgn_update;
72920Sjbeloro }
73920Sjbeloro
74920Sjbeloro /*
752558Szx151605 * these two dummy functions are loaded over the original
762558Szx151605 * todm5823 set and clear_power_alarm functions. On Boston
772558Szx151605 * these functions are not supported, and thus we need to provide
782558Szx151605 * dummy functions that just returns.
792558Szx151605 * On Boston, clock chip is not persistant across reboots,
802558Szx151605 * and moreover it has a bug sending memory access.
812558Szx151605 * This fix is done by writing over the original
822558Szx151605 * tod_ops function pointer with our dummy replacement functions.
832558Szx151605 */
842558Szx151605 /*ARGSUSED*/
852558Szx151605 static void
dummy_todm5823_set_power_alarm(timestruc_t ts)862558Szx151605 dummy_todm5823_set_power_alarm(timestruc_t ts)
872558Szx151605 {
882558Szx151605 }
892558Szx151605
902558Szx151605 static void
dummy_todm5823_clear_power_alarm(void)912558Szx151605 dummy_todm5823_clear_power_alarm(void)
922558Szx151605 {
932558Szx151605 }
942558Szx151605
952558Szx151605 /*
96920Sjbeloro * Definitions for accessing the pci config space of the isa node
97920Sjbeloro * of Southbridge.
98920Sjbeloro */
99920Sjbeloro static ddi_acc_handle_t isa_handle = NULL; /* handle for isa pci space */
100920Sjbeloro
101920Sjbeloro /*
102920Sjbeloro * Definition for accessing rmclomv
103920Sjbeloro */
104920Sjbeloro #define RMCLOMV_PATHNAME "/pseudo/rmclomv@0"
105920Sjbeloro
106920Sjbeloro void
load_platform_drivers(void)107920Sjbeloro load_platform_drivers(void)
108920Sjbeloro {
109920Sjbeloro /*
110920Sjbeloro * It is OK to return error because 'us' driver is not available
111920Sjbeloro * in all clusters (e.g. missing in Core cluster).
112920Sjbeloro */
113920Sjbeloro (void) i_ddi_attach_hw_nodes("us");
114920Sjbeloro
115920Sjbeloro
116920Sjbeloro /*
117920Sjbeloro * mc-us3i must stay loaded for plat_get_mem_unum()
118920Sjbeloro */
119920Sjbeloro if (i_ddi_attach_hw_nodes("mc-us3i") != DDI_SUCCESS)
120920Sjbeloro cmn_err(CE_WARN, "mc-us3i driver failed to install");
121920Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("mc-us3i"));
122920Sjbeloro
123920Sjbeloro /*
124920Sjbeloro * load the power button driver
125920Sjbeloro */
126920Sjbeloro if (i_ddi_attach_hw_nodes("power") != DDI_SUCCESS)
127920Sjbeloro cmn_err(CE_WARN, "power button driver failed to install");
128920Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("power"));
129920Sjbeloro
130920Sjbeloro /*
131920Sjbeloro * load the GPIO driver for the ALOM reset and watchdog lines
132920Sjbeloro */
133920Sjbeloro if (i_ddi_attach_hw_nodes("pmugpio") != DDI_SUCCESS)
134920Sjbeloro cmn_err(CE_WARN, "pmugpio failed to install");
135920Sjbeloro else {
136920Sjbeloro extern int watchdog_enable, watchdog_available;
137920Sjbeloro extern int disable_watchdog_on_exit;
138920Sjbeloro
139920Sjbeloro /*
140920Sjbeloro * Disable an active h/w watchdog timer upon exit to OBP.
141920Sjbeloro */
142920Sjbeloro disable_watchdog_on_exit = 1;
143920Sjbeloro
144920Sjbeloro watchdog_enable = 1;
145920Sjbeloro watchdog_available = 1;
146920Sjbeloro }
147920Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("pmugpio"));
148920Sjbeloro
149920Sjbeloro /*
150920Sjbeloro * Figure out which mi2cv dip is shared with OBP for the nvram
151920Sjbeloro * device, so the lock can be acquired.
152920Sjbeloro */
153920Sjbeloro shared_mi2cv_dip = e_ddi_hold_devi_by_path(SHARED_MI2CV_PATH, 0);
154920Sjbeloro
155920Sjbeloro /*
156920Sjbeloro * Load the environmentals driver (rmclomv)
157920Sjbeloro *
158920Sjbeloro * We need this driver to handle events from the RMC when state
159920Sjbeloro * changes occur in the environmental data.
160920Sjbeloro */
161920Sjbeloro if (i_ddi_attach_hw_nodes("rmc_comm") != DDI_SUCCESS) {
162920Sjbeloro cmn_err(CE_WARN, "rmc_comm failed to install");
163920Sjbeloro } else {
164920Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("rmc_comm"));
165920Sjbeloro
166920Sjbeloro if (e_ddi_hold_devi_by_path(RMCLOMV_PATHNAME, 0) == NULL) {
167920Sjbeloro cmn_err(CE_WARN, "Could not install rmclomv driver\n");
168920Sjbeloro }
169920Sjbeloro }
1702558Szx151605
1712558Szx151605 /*
1722558Szx151605 * These two dummy functions are loaded over the original
1732558Szx151605 * todm5823 set and clear_power_alarm functions. On Boston,
1742558Szx151605 * these functionalities are not supported.
1752558Szx151605 * The load_platform_drivers(void) is called from post_startup()
1762558Szx151605 * which is after all the initialization of the tod module is
1772558Szx151605 * finished, then we replace 2 of the tod_ops function pointers
1782558Szx151605 * with our dummy version.
1792558Szx151605 */
1802558Szx151605 tod_ops.tod_set_power_alarm = dummy_todm5823_set_power_alarm;
1812558Szx151605 tod_ops.tod_clear_power_alarm = dummy_todm5823_clear_power_alarm;
1822558Szx151605
183920Sjbeloro /*
184920Sjbeloro * create a handle to the rmc_comm_request_nowait() function
185920Sjbeloro * inside the rmc_comm module.
186920Sjbeloro *
187920Sjbeloro * The Seattle/Boston todm5823 driver will use this handle to
188920Sjbeloro * use the rmc_comm_request_nowait() function to send time/date
189920Sjbeloro * updates to ALOM.
190920Sjbeloro */
191920Sjbeloro rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t))
1925648Ssetje modgetsymvalue("rmc_comm_request_nowait", 0);
193920Sjbeloro }
194920Sjbeloro
195920Sjbeloro /*
196920Sjbeloro * This routine is needed if a device error or timeout occurs before the
197920Sjbeloro * driver is loaded.
198920Sjbeloro */
199920Sjbeloro /*ARGSUSED*/
200920Sjbeloro int
plat_ide_chipreset(dev_info_t * dip,int chno)201920Sjbeloro plat_ide_chipreset(dev_info_t *dip, int chno)
202920Sjbeloro {
203920Sjbeloro int ret = DDI_SUCCESS;
204920Sjbeloro
205920Sjbeloro if (isa_handle == NULL) {
206920Sjbeloro return (DDI_FAILURE);
207920Sjbeloro }
208920Sjbeloro
209920Sjbeloro /*
210920Sjbeloro * This will be filled in with the reset logic
211920Sjbeloro * for the ULI1573 when that becomes available.
212920Sjbeloro * currently this is just a stub.
213920Sjbeloro */
214920Sjbeloro return (ret);
215920Sjbeloro }
216920Sjbeloro
217920Sjbeloro
218920Sjbeloro /*ARGSUSED*/
219920Sjbeloro int
plat_cpu_poweron(struct cpu * cp)220920Sjbeloro plat_cpu_poweron(struct cpu *cp)
221920Sjbeloro {
222920Sjbeloro return (ENOTSUP); /* not supported on this platform */
223920Sjbeloro }
224920Sjbeloro
225920Sjbeloro /*ARGSUSED*/
226920Sjbeloro int
plat_cpu_poweroff(struct cpu * cp)227920Sjbeloro plat_cpu_poweroff(struct cpu *cp)
228920Sjbeloro {
229920Sjbeloro return (ENOTSUP); /* not supported on this platform */
230920Sjbeloro }
231920Sjbeloro
232920Sjbeloro /*ARGSUSED*/
233920Sjbeloro void
plat_freelist_process(int mnode)234920Sjbeloro plat_freelist_process(int mnode)
235920Sjbeloro {
236920Sjbeloro }
237920Sjbeloro
238920Sjbeloro char *platform_module_list[] = {
239920Sjbeloro "mi2cv",
240920Sjbeloro "pca9556",
241920Sjbeloro (char *)0
242920Sjbeloro };
243920Sjbeloro
244920Sjbeloro /*ARGSUSED*/
245920Sjbeloro void
plat_tod_fault(enum tod_fault_type tod_bad)246920Sjbeloro plat_tod_fault(enum tod_fault_type tod_bad)
247920Sjbeloro {
248920Sjbeloro }
249920Sjbeloro
250920Sjbeloro /*ARGSUSED*/
251920Sjbeloro 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)252920Sjbeloro plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
253920Sjbeloro int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
254920Sjbeloro {
255920Sjbeloro if (flt_in_memory && (p2get_mem_unum != NULL))
256920Sjbeloro return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
257920Sjbeloro buf, buflen, lenp));
258920Sjbeloro else
259920Sjbeloro return (ENOTSUP);
260920Sjbeloro }
261920Sjbeloro
262920Sjbeloro /*
263920Sjbeloro * This platform hook gets called from mc_add_mem_unum_label() in the mc-us3i
264920Sjbeloro * driver giving each platform the opportunity to add platform
265920Sjbeloro * specific label information to the unum for ECC error logging purposes.
266920Sjbeloro */
267920Sjbeloro /*ARGSUSED*/
268920Sjbeloro void
plat_add_mem_unum_label(char * unum,int mcid,int bank,int dimm)269920Sjbeloro plat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm)
270920Sjbeloro {
271920Sjbeloro char old_unum[UNUM_NAMLEN];
272920Sjbeloro int printed;
273920Sjbeloro int buflen = UNUM_NAMLEN;
274920Sjbeloro
275*11311SSurya.Prakki@Sun.COM (void) strcpy(old_unum, unum);
2761185Sjroberts printed = snprintf(unum, buflen, "MB/C%d/P0/B%d", mcid, bank);
277920Sjbeloro buflen -= printed;
278920Sjbeloro unum += printed;
279920Sjbeloro
280920Sjbeloro if (dimm != -1) {
281920Sjbeloro printed = snprintf(unum, buflen, "/D%d", dimm);
282920Sjbeloro buflen -= printed;
283920Sjbeloro unum += printed;
284920Sjbeloro }
285920Sjbeloro
286*11311SSurya.Prakki@Sun.COM (void) snprintf(unum, buflen, ": %s", old_unum);
287920Sjbeloro }
288920Sjbeloro
289920Sjbeloro /*ARGSUSED*/
290920Sjbeloro int
plat_get_cpu_unum(int cpuid,char * buf,int buflen,int * lenp)291920Sjbeloro plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
292920Sjbeloro {
2931302Sjroberts if (snprintf(buf, buflen, "MB/C%d", cpuid) >= buflen) {
294920Sjbeloro return (ENOSPC);
295920Sjbeloro } else {
296920Sjbeloro *lenp = strlen(buf);
297920Sjbeloro return (0);
298920Sjbeloro }
299920Sjbeloro }
300920Sjbeloro
301920Sjbeloro /*
302920Sjbeloro * Our nodename has been set, pass it along to the RMC.
303920Sjbeloro */
304920Sjbeloro void
plat_nodename_set(void)305920Sjbeloro plat_nodename_set(void)
306920Sjbeloro {
307920Sjbeloro rmc_comm_msg_t req; /* request */
308920Sjbeloro int (*rmc_req_res)(rmc_comm_msg_t *, rmc_comm_msg_t *, time_t) = NULL;
309920Sjbeloro
310920Sjbeloro /*
311920Sjbeloro * find the symbol for the mailbox routine
312920Sjbeloro */
313920Sjbeloro rmc_req_res = (int (*)(rmc_comm_msg_t *, rmc_comm_msg_t *, time_t))
3145648Ssetje modgetsymvalue("rmc_comm_request_response", 0);
315920Sjbeloro
316920Sjbeloro if (rmc_req_res == NULL) {
317920Sjbeloro return;
318920Sjbeloro }
319920Sjbeloro
320920Sjbeloro /*
321920Sjbeloro * construct the message telling the RMC our nodename
322920Sjbeloro */
323920Sjbeloro req.msg_type = DP_SET_CPU_NODENAME;
324920Sjbeloro req.msg_len = strlen(utsname.nodename) + 1;
325920Sjbeloro req.msg_bytes = 0;
326920Sjbeloro req.msg_buf = (caddr_t)utsname.nodename;
327920Sjbeloro
328920Sjbeloro /*
329920Sjbeloro * ship it
330920Sjbeloro */
331920Sjbeloro (void) (rmc_req_res)(&req, NULL, 2000);
332920Sjbeloro }
333920Sjbeloro
334920Sjbeloro sig_state_t current_sgn;
335920Sjbeloro
336920Sjbeloro /*
337920Sjbeloro * cpu signatures - we're only interested in the overall system
338920Sjbeloro * "signature" on this platform - not individual cpu signatures
339920Sjbeloro */
340920Sjbeloro /*ARGSUSED*/
341920Sjbeloro static void
cpu_sgn_update(ushort_t sig,uchar_t state,uchar_t sub_state,int cpuid)342920Sjbeloro cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid)
343920Sjbeloro {
344920Sjbeloro dp_cpu_signature_t signature;
345920Sjbeloro rmc_comm_msg_t req; /* request */
346920Sjbeloro int (*rmc_req_now)(rmc_comm_msg_t *, uint8_t) = NULL;
347920Sjbeloro
348920Sjbeloro
349920Sjbeloro /*
350920Sjbeloro * Differentiate a panic reboot from a non-panic reboot in the
351920Sjbeloro * setting of the substate of the signature.
352920Sjbeloro *
353920Sjbeloro * If the new substate is REBOOT and we're rebooting due to a panic,
354920Sjbeloro * then set the new substate to a special value indicating a panic
355920Sjbeloro * reboot, SIGSUBST_PANIC_REBOOT.
356920Sjbeloro *
357920Sjbeloro * A panic reboot is detected by a current (previous) signature
358920Sjbeloro * state of SIGST_EXIT, and a new signature substate of SIGSUBST_REBOOT.
359920Sjbeloro * The domain signature state SIGST_EXIT is used as the panic flow
360920Sjbeloro * progresses.
361920Sjbeloro *
362920Sjbeloro * At the end of the panic flow, the reboot occurs but we should know
363920Sjbeloro * one that was involuntary, something that may be quite useful to know
364920Sjbeloro * at OBP level.
365920Sjbeloro */
366920Sjbeloro if (state == SIGST_EXIT && sub_state == SIGSUBST_REBOOT) {
367920Sjbeloro if (current_sgn.state_t.state == SIGST_EXIT &&
368920Sjbeloro current_sgn.state_t.sub_state != SIGSUBST_REBOOT)
369920Sjbeloro sub_state = SIGSUBST_PANIC_REBOOT;
370920Sjbeloro }
371920Sjbeloro
372920Sjbeloro /*
373920Sjbeloro * offline and detached states only apply to a specific cpu
374920Sjbeloro * so ignore them.
375920Sjbeloro */
376920Sjbeloro if (state == SIGST_OFFLINE || state == SIGST_DETACHED) {
377920Sjbeloro return;
378920Sjbeloro }
379920Sjbeloro
380920Sjbeloro current_sgn.signature = CPU_SIG_BLD(sig, state, sub_state);
381920Sjbeloro
382920Sjbeloro /*
383920Sjbeloro * find the symbol for the mailbox routine
384920Sjbeloro */
385920Sjbeloro rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t))
3865648Ssetje modgetsymvalue("rmc_comm_request_nowait", 0);
387920Sjbeloro if (rmc_req_now == NULL) {
388920Sjbeloro return;
389920Sjbeloro }
390920Sjbeloro
391920Sjbeloro signature.cpu_id = -1;
392920Sjbeloro signature.sig = sig;
393920Sjbeloro signature.states = state;
394920Sjbeloro signature.sub_state = sub_state;
395920Sjbeloro req.msg_type = DP_SET_CPU_SIGNATURE;
396920Sjbeloro req.msg_len = (int)(sizeof (signature));
397920Sjbeloro req.msg_bytes = 0;
398920Sjbeloro req.msg_buf = (caddr_t)&signature;
399920Sjbeloro
400920Sjbeloro /*
4014052Sphilippm * We need to tell the SP that the host is about to stop running. The
4024052Sphilippm * SP will then allow the date to be set at its console, it will change
4034052Sphilippm * state of the activity indicator, it will display the correct host
4044052Sphilippm * status, and it will stop sending console messages and alerts to the
4054052Sphilippm * host communication channel.
4064052Sphilippm *
4074052Sphilippm * This requires the RMC_COMM_DREQ_URGENT as we want to
4084052Sphilippm * be sure activity indicators will reflect the correct status.
4094052Sphilippm *
4104052Sphilippm * When sub_state SIGSUBST_DUMP is sent, the urgent flag
4114052Sphilippm * (RMC_COMM_DREQ_URGENT) is not required as SIGSUBST_PANIC_REBOOT
4124052Sphilippm * has already been sent and changed activity indicators.
413920Sjbeloro */
414920Sjbeloro if (state == SIGST_EXIT && (sub_state == SIGSUBST_HALT ||
415920Sjbeloro sub_state == SIGSUBST_REBOOT || sub_state == SIGSUBST_ENVIRON ||
416920Sjbeloro sub_state == SIGSUBST_PANIC_REBOOT))
417920Sjbeloro (void) (rmc_req_now)(&req, RMC_COMM_DREQ_URGENT);
418920Sjbeloro else
4191779Sfw157321 (void) (rmc_req_now)(&req, 0);
420920Sjbeloro }
421920Sjbeloro
422920Sjbeloro /*
423920Sjbeloro * Fiesta support for lgroups.
424920Sjbeloro *
425920Sjbeloro * On fiesta platform, an lgroup platform handle == CPU id
426920Sjbeloro */
427920Sjbeloro
428920Sjbeloro /*
429920Sjbeloro * Macro for extracting the CPU number from the CPU id
430920Sjbeloro */
431920Sjbeloro #define CPUID_TO_LGRP(id) ((id) & 0x7)
432920Sjbeloro #define PLATFORM_MC_SHIFT 36
433920Sjbeloro
434920Sjbeloro /*
435920Sjbeloro * Return the platform handle for the lgroup containing the given CPU
436920Sjbeloro */
437920Sjbeloro void *
plat_lgrp_cpu_to_hand(processorid_t id)438920Sjbeloro plat_lgrp_cpu_to_hand(processorid_t id)
439920Sjbeloro {
440969Sanovick return ((void *)(uintptr_t)CPUID_TO_LGRP(id));
441920Sjbeloro }
442920Sjbeloro
443920Sjbeloro /*
444920Sjbeloro * Platform specific lgroup initialization
445920Sjbeloro */
446920Sjbeloro void
plat_lgrp_init(void)447920Sjbeloro plat_lgrp_init(void)
448920Sjbeloro {
449920Sjbeloro pnode_t curnode;
4501297Sanovick char tmp_name[sizeof (OBP_CPU) + 1]; /* extra padding */
451920Sjbeloro int portid;
452920Sjbeloro int cpucnt = 0;
453920Sjbeloro int max_portid = -1;
454920Sjbeloro extern uint32_t lgrp_expand_proc_thresh;
455920Sjbeloro extern uint32_t lgrp_expand_proc_diff;
456920Sjbeloro extern pgcnt_t lgrp_mem_free_thresh;
457920Sjbeloro extern uint32_t lgrp_loadavg_tolerance;
458920Sjbeloro extern uint32_t lgrp_loadavg_max_effect;
459920Sjbeloro extern uint32_t lgrp_load_thresh;
460920Sjbeloro extern lgrp_mem_policy_t lgrp_mem_policy_root;
461920Sjbeloro
462920Sjbeloro /*
463920Sjbeloro * Count the number of CPUs installed to determine if
464920Sjbeloro * NUMA optimization should be enabled or not.
465920Sjbeloro *
466920Sjbeloro * All CPU nodes reside in the root node and have a
467920Sjbeloro * device type "cpu".
468920Sjbeloro */
469920Sjbeloro curnode = prom_rootnode();
470920Sjbeloro for (curnode = prom_childnode(curnode); curnode;
471920Sjbeloro curnode = prom_nextnode(curnode)) {
4721297Sanovick bzero(tmp_name, sizeof (tmp_name));
4731297Sanovick if (prom_bounded_getprop(curnode, OBP_DEVICETYPE, tmp_name,
4741297Sanovick sizeof (OBP_CPU)) == -1 || strcmp(tmp_name, OBP_CPU) != 0)
475920Sjbeloro continue;
476920Sjbeloro
4771297Sanovick cpucnt++;
4781297Sanovick
4791297Sanovick if (prom_getprop(curnode, "portid", (caddr_t)&portid) !=
4801297Sanovick -1 && portid > max_portid)
4811297Sanovick max_portid = portid;
482920Sjbeloro }
483920Sjbeloro if (cpucnt <= 1)
484920Sjbeloro max_mem_nodes = 1;
485920Sjbeloro else if (max_portid >= 0 && max_portid < MAX_MEM_NODES)
486920Sjbeloro max_mem_nodes = max_portid + 1;
487920Sjbeloro
488920Sjbeloro /*
489920Sjbeloro * Set tuneables for fiesta architecture
490920Sjbeloro *
491920Sjbeloro * lgrp_expand_proc_thresh is the minimum load on the lgroups
492920Sjbeloro * this process is currently running on before considering
493920Sjbeloro * expanding threads to another lgroup.
494920Sjbeloro *
495920Sjbeloro * lgrp_expand_proc_diff determines how much less the remote lgroup
496920Sjbeloro * must be loaded before expanding to it.
497920Sjbeloro *
498920Sjbeloro * Optimize for memory bandwidth by spreading multi-threaded
499920Sjbeloro * program to different lgroups.
500920Sjbeloro */
501920Sjbeloro lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1;
502920Sjbeloro lgrp_expand_proc_diff = lgrp_loadavg_max_effect / 2;
503920Sjbeloro lgrp_loadavg_tolerance = lgrp_loadavg_max_effect / 2;
504920Sjbeloro lgrp_mem_free_thresh = 1; /* home lgrp must have some memory */
505920Sjbeloro lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1;
506920Sjbeloro lgrp_mem_policy_root = LGRP_MEM_POLICY_NEXT;
507920Sjbeloro lgrp_load_thresh = 0;
508920Sjbeloro
509920Sjbeloro mem_node_pfn_shift = PLATFORM_MC_SHIFT - MMU_PAGESHIFT;
510920Sjbeloro }
511920Sjbeloro
512920Sjbeloro /*
513920Sjbeloro * Return latency between "from" and "to" lgroups
514920Sjbeloro *
515920Sjbeloro * This latency number can only be used for relative comparison
516920Sjbeloro * between lgroups on the running system, cannot be used across platforms,
517920Sjbeloro * and may not reflect the actual latency. It is platform and implementation
518920Sjbeloro * specific, so platform gets to decide its value. It would be nice if the
519920Sjbeloro * number was at least proportional to make comparisons more meaningful though.
520920Sjbeloro * NOTE: The numbers below are supposed to be load latencies for uncached
521920Sjbeloro * memory divided by 10.
522920Sjbeloro */
523920Sjbeloro int
plat_lgrp_latency(void * from,void * to)524920Sjbeloro plat_lgrp_latency(void *from, void *to)
525920Sjbeloro {
526920Sjbeloro /*
527920Sjbeloro * Return remote latency when there are more than two lgroups
528920Sjbeloro * (root and child) and getting latency between two different
529920Sjbeloro * lgroups or root is involved
530920Sjbeloro */
531920Sjbeloro if (lgrp_optimizations() && (from != to || from ==
532920Sjbeloro (void *) LGRP_DEFAULT_HANDLE || to == (void *) LGRP_DEFAULT_HANDLE))
533920Sjbeloro return (17);
534920Sjbeloro else
535920Sjbeloro return (12);
536920Sjbeloro }
537920Sjbeloro
538920Sjbeloro int
plat_pfn_to_mem_node(pfn_t pfn)539920Sjbeloro plat_pfn_to_mem_node(pfn_t pfn)
540920Sjbeloro {
541920Sjbeloro ASSERT(max_mem_nodes > 1);
542920Sjbeloro return (pfn >> mem_node_pfn_shift);
543920Sjbeloro }
544920Sjbeloro
545920Sjbeloro /*
546920Sjbeloro * Assign memnode to lgroups
547920Sjbeloro */
548920Sjbeloro void
plat_fill_mc(pnode_t nodeid)549920Sjbeloro plat_fill_mc(pnode_t nodeid)
550920Sjbeloro {
551920Sjbeloro int portid;
552920Sjbeloro
553920Sjbeloro /*
554920Sjbeloro * Memory controller portid == global CPU id
555920Sjbeloro */
556920Sjbeloro if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) == -1) ||
557920Sjbeloro (portid < 0))
558920Sjbeloro return;
559920Sjbeloro
560920Sjbeloro if (portid < max_mem_nodes)
561920Sjbeloro plat_assign_lgrphand_to_mem_node((lgrp_handle_t)portid, portid);
562920Sjbeloro }
563920Sjbeloro
564920Sjbeloro
565920Sjbeloro /*
566920Sjbeloro * Common locking enter code
567920Sjbeloro */
568920Sjbeloro void
plat_setprop_enter(void)569920Sjbeloro plat_setprop_enter(void)
570920Sjbeloro {
571920Sjbeloro mutex_enter(&mi2cv_mutex);
572920Sjbeloro }
573920Sjbeloro
574920Sjbeloro /*
575920Sjbeloro * Common locking exit code
576920Sjbeloro */
577920Sjbeloro void
plat_setprop_exit(void)578920Sjbeloro plat_setprop_exit(void)
579920Sjbeloro {
580920Sjbeloro mutex_exit(&mi2cv_mutex);
581920Sjbeloro }
582920Sjbeloro
583920Sjbeloro /*
584920Sjbeloro * Called by mi2cv driver
585920Sjbeloro */
586920Sjbeloro void
plat_shared_i2c_enter(dev_info_t * i2cnexus_dip)587920Sjbeloro plat_shared_i2c_enter(dev_info_t *i2cnexus_dip)
588920Sjbeloro {
589920Sjbeloro if (i2cnexus_dip == shared_mi2cv_dip) {
590920Sjbeloro plat_setprop_enter();
591920Sjbeloro }
592920Sjbeloro }
593920Sjbeloro
594920Sjbeloro /*
595920Sjbeloro * Called by mi2cv driver
596920Sjbeloro */
597920Sjbeloro void
plat_shared_i2c_exit(dev_info_t * i2cnexus_dip)598920Sjbeloro plat_shared_i2c_exit(dev_info_t *i2cnexus_dip)
599920Sjbeloro {
600920Sjbeloro if (i2cnexus_dip == shared_mi2cv_dip) {
601920Sjbeloro plat_setprop_exit();
602920Sjbeloro }
603920Sjbeloro }
604920Sjbeloro
605920Sjbeloro /*
606920Sjbeloro * Called by todm5823 driver
607920Sjbeloro */
608920Sjbeloro void
plat_rmc_comm_req(struct rmc_comm_msg * request)609920Sjbeloro plat_rmc_comm_req(struct rmc_comm_msg *request)
610920Sjbeloro {
611920Sjbeloro if (rmc_req_now)
612920Sjbeloro (void) rmc_req_now(request, 0);
613920Sjbeloro }
614