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
startup_platform(void)52 startup_platform(void)
53 {
54 mutex_init(&chicago_mi2cv_mutex, NULL, MUTEX_ADAPTIVE, NULL);
55 }
56
57 int
set_platform_tsb_spares()58 set_platform_tsb_spares()
59 {
60 return (0);
61 }
62
63 void
set_platform_defaults(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
load_platform_drivers(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
plat_cpu_poweron(struct cpu * cp)123 plat_cpu_poweron(struct cpu *cp)
124 {
125 return (ENOTSUP); /* not supported on this platform */
126 }
127
128 /*ARGSUSED*/
129 int
plat_cpu_poweroff(struct cpu * cp)130 plat_cpu_poweroff(struct cpu *cp)
131 {
132 return (ENOTSUP); /* not supported on this platform */
133 }
134
135 /*ARGSUSED*/
136 void
plat_freelist_process(int mnode)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
plat_tod_fault(enum tod_fault_type tod_bad)151 plat_tod_fault(enum tod_fault_type tod_bad)
152 {
153 }
154
155 /*ARGSUSED*/
156 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)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
plat_get_cpu_unum(int cpuid,char * buf,int buflen,int * lenp)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 *
plat_lgrp_cpu_to_hand(processorid_t id)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
plat_lgrp_init(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
plat_lgrp_latency(lgrp_handle_t from,lgrp_handle_t to)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
plat_pfn_to_mem_node(pfn_t pfn)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
plat_fill_mc(pnode_t nodeid)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
plat_setprop_enter(void)324 plat_setprop_enter(void)
325 {
326 mutex_enter(&chicago_mi2cv_mutex);
327 }
328
329 /*
330 * Common locking exit code
331 */
332 void
plat_setprop_exit(void)333 plat_setprop_exit(void)
334 {
335 mutex_exit(&chicago_mi2cv_mutex);
336 }
337
338 /*
339 * Called by mi2cv driver
340 */
341 void
plat_shared_i2c_enter(dev_info_t * i2cnexus_dip)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
plat_shared_i2c_exit(dev_info_t * i2cnexus_dip)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
get_ebus_rtc_vaddr()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