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