xref: /illumos-gate/usr/src/uts/sun4u/daktari/os/daktari.c (revision 60a3f738d56f92ae8b80e4b62a2331c6e1f2311f)
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 2006 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/cpuvar.h>
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/sunddi.h>
32 #include <sys/ddi.h>
33 #include <sys/sysmacros.h>
34 #include <sys/note.h>
35 
36 #include <sys/modctl.h>		/* for modload() */
37 #include <sys/platform_module.h>
38 #include <sys/errno.h>
39 #include <sys/daktari.h>
40 #include <sys/machsystm.h>
41 #include <sys/promif.h>
42 #include <vm/page.h>
43 #include <sys/memnode.h>
44 #include <vm/vm_dep.h>
45 
46 /* I2C Stuff */
47 #include <sys/i2c/clients/i2c_client.h>
48 
49 
50 int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
51 
52 /* Daktari Keyswitch Information */
53 #define	DAK_KEY_POLL_PORT	3
54 #define	DAK_KEY_POLL_BIT	2
55 #define	DAK_KEY_POLL_INTVL	10
56 
57 static	boolean_t	key_locked_bit;
58 static	clock_t		keypoll_timeout_hz;
59 
60 /*
61  * Table that maps memory slices to a specific memnode.
62  */
63 int slice_to_memnode[DAK_MAX_SLICE];
64 
65 /*
66  * For software memory interleaving support.
67  */
68 static	void update_mem_bounds(int, int, int, uint64_t, uint64_t);
69 
70 static uint64_t
71 slice_table[DAK_SBD_SLOTS][DAK_CPUS_PER_BOARD][DAK_BANKS_PER_MC][2];
72 
73 #define	SLICE_PA	0
74 #define	SLICE_SPAN	1
75 
76 int (*daktari_ssc050_get_port_bit) (dev_info_t *, int, int, uint8_t *, int);
77 extern	void (*abort_seq_handler)();
78 static	int daktari_dev_search(dev_info_t *, void *);
79 static	void keyswitch_poll(void *);
80 static	void daktari_abort_seq_handler(char *msg);
81 
82 void
83 startup_platform(void)
84 {
85 	/*
86 	 * Disable an active h/w watchdog timer
87 	 * upon exit to OBP.
88 	 */
89 	extern int disable_watchdog_on_exit;
90 	disable_watchdog_on_exit = 1;
91 }
92 
93 int
94 set_platform_tsb_spares()
95 {
96 	return (0);
97 }
98 
99 #pragma weak mmu_init_large_pages
100 
101 void
102 set_platform_defaults(void)
103 {
104 	extern void mmu_init_large_pages(size_t);
105 
106 	if ((mmu_page_sizes == max_mmu_page_sizes) &&
107 	    (mmu_ism_pagesize != DEFAULT_ISM_PAGESIZE)) {
108 		if (&mmu_init_large_pages)
109 			mmu_init_large_pages(mmu_ism_pagesize);
110 	}
111 }
112 
113 void
114 load_platform_modules(void)
115 {
116 	if (modload("misc", "pcihp") < 0) {
117 		cmn_err(CE_NOTE, "pcihp driver failed to load");
118 	}
119 	if (modload("drv", "pmc") < 0) {
120 		cmn_err(CE_NOTE, "pmc driver failed to load");
121 	}
122 
123 }
124 
125 void
126 load_platform_drivers(void)
127 {
128 	char **drv;
129 	dev_info_t	*keysw_dip;
130 
131 	static char *boot_time_drivers[] = {
132 		"hpc3130",
133 		"todds1287",
134 		"mc-us3",
135 		"ssc050",
136 		"pcisch",
137 		NULL
138 	};
139 
140 	for (drv = boot_time_drivers; *drv; drv++) {
141 		if (i_ddi_attach_hw_nodes(*drv) != DDI_SUCCESS)
142 			cmn_err(CE_WARN, "Failed to install \"%s\" driver.",
143 			    *drv);
144 	}
145 
146 	/*
147 	 * mc-us3 & ssc050 must stay loaded for plat_get_mem_unum()
148 	 * and keyswitch_poll()
149 	 */
150 	(void) ddi_hold_driver(ddi_name_to_major("mc-us3"));
151 	(void) ddi_hold_driver(ddi_name_to_major("ssc050"));
152 
153 	/* Gain access into the ssc050_get_port function */
154 	daktari_ssc050_get_port_bit = (int (*) (dev_info_t *, int, int,
155 		uint8_t *, int)) modgetsymvalue("ssc050_get_port_bit", 0);
156 	if (daktari_ssc050_get_port_bit == NULL) {
157 		cmn_err(CE_WARN, "cannot find ssc050_get_port_bit");
158 		return;
159 	}
160 
161 	ddi_walk_devs(ddi_root_node(), daktari_dev_search, (void *)&keysw_dip);
162 	ASSERT(keysw_dip != NULL);
163 
164 	keypoll_timeout_hz = drv_usectohz(10 * MICROSEC);
165 	keyswitch_poll(keysw_dip);
166 	abort_seq_handler = daktari_abort_seq_handler;
167 }
168 
169 static int
170 daktari_dev_search(dev_info_t *dip, void *arg)
171 {
172 	char		*compatible = NULL; /* Search tree for "i2c-ssc050" */
173 	int		*dev_regs; /* Info about where the device is. */
174 	uint_t		len;
175 	int		err;
176 
177 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
178 				"compatible", &compatible) != DDI_PROP_SUCCESS)
179 		return (DDI_WALK_CONTINUE);
180 
181 	if (strcmp(compatible, "i2c-ssc050") == 0) {
182 		ddi_prop_free(compatible);
183 
184 		err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
185 			DDI_PROP_DONTPASS, "reg", &dev_regs, &len);
186 		if (err != DDI_PROP_SUCCESS) {
187 			return (DDI_WALK_CONTINUE);
188 		}
189 		/*
190 		 * regs[0] contains the bus number and regs[1]
191 		 * contains the device address of the i2c device.
192 		 * 0x82 is the device address of the i2c device
193 		 * from which  the key switch position is read.
194 		 */
195 		if (dev_regs[0] == 0 && dev_regs[1] == 0x82) {
196 			*((dev_info_t **)arg) = dip;
197 			ddi_prop_free(dev_regs);
198 			return (DDI_WALK_TERMINATE);
199 		}
200 		ddi_prop_free(dev_regs);
201 	} else {
202 		ddi_prop_free(compatible);
203 	}
204 	return (DDI_WALK_CONTINUE);
205 }
206 
207 static void
208 keyswitch_poll(void *arg)
209 {
210 	dev_info_t	*dip = arg;
211 	uchar_t	port_byte;
212 	int	port = DAK_KEY_POLL_PORT;
213 	int	bit = DAK_KEY_POLL_BIT;
214 	int	err;
215 
216 	err = daktari_ssc050_get_port_bit(dip, port, bit,
217 		&port_byte, I2C_NOSLEEP);
218 	if (err != 0) {
219 		return;
220 	}
221 
222 	key_locked_bit = (boolean_t)((port_byte & 0x1));
223 	timeout(keyswitch_poll, (caddr_t)dip, keypoll_timeout_hz);
224 }
225 
226 static void
227 daktari_abort_seq_handler(char *msg)
228 {
229 	if (key_locked_bit == 0)
230 		cmn_err(CE_CONT, "KEY in LOCKED position, "
231 			"ignoring debug enter sequence");
232 	else  {
233 		debug_enter(msg);
234 	}
235 }
236 
237 
238 int
239 plat_cpu_poweron(struct cpu *cp)
240 {
241 	_NOTE(ARGUNUSED(cp))
242 	return (ENOTSUP);
243 }
244 
245 int
246 plat_cpu_poweroff(struct cpu *cp)
247 {
248 	_NOTE(ARGUNUSED(cp))
249 	return (ENOTSUP);
250 }
251 
252 /*
253  * Given a pfn, return the board and beginning/end of the page's
254  * memory controller's address range.
255  */
256 static int
257 plat_discover_slice(pfn_t pfn, pfn_t *first, pfn_t *last)
258 {
259 	int bd, cpu, bank;
260 
261 	for (bd = 0; bd < DAK_SBD_SLOTS; bd++) {
262 		for (cpu = 0; cpu < DAK_CPUS_PER_BOARD; cpu++) {
263 			for (bank = 0; bank < DAK_BANKS_PER_MC; bank++) {
264 				uint64_t *slice = slice_table[bd][cpu][bank];
265 				uint64_t base = btop(slice[SLICE_PA]);
266 				uint64_t len = btop(slice[SLICE_SPAN]);
267 				if (len && pfn >= base && pfn < (base + len)) {
268 					*first = base;
269 					*last = base + len - 1;
270 					return (bd);
271 				}
272 			}
273 		}
274 	}
275 	panic("plat_discover_slice: no slice for pfn 0x%lx\n", pfn);
276 	/* NOTREACHED */
277 }
278 
279 /*ARGSUSED*/
280 void
281 plat_freelist_process(int mnode)
282 {}
283 
284 
285 /*
286  * Called for each board/cpu/PA range detected in plat_fill_mc().
287  */
288 static void
289 update_mem_bounds(int boardid, int cpuid, int bankid,
290 	uint64_t base, uint64_t size)
291 {
292 	uint64_t	end;
293 	int		mnode;
294 
295 	slice_table[boardid][cpuid][bankid][SLICE_PA] = base;
296 	slice_table[boardid][cpuid][bankid][SLICE_SPAN] = size;
297 
298 	end = base + size - 1;
299 
300 	/*
301 	 * First see if this board already has a memnode associated
302 	 * with it.  If not, see if this slice has a memnode.  This
303 	 * covers the cases where a single slice covers multiple
304 	 * boards (cross-board interleaving) and where a single
305 	 * board has multiple slices (1+GB DIMMs).
306 	 */
307 	if ((mnode = plat_lgrphand_to_mem_node(boardid)) == -1) {
308 		if ((mnode = slice_to_memnode[PA_2_SLICE(base)]) == -1)
309 			mnode = mem_node_alloc();
310 
311 		ASSERT(mnode >= 0);
312 		ASSERT(mnode < MAX_MEM_NODES);
313 		plat_assign_lgrphand_to_mem_node(boardid, mnode);
314 	}
315 
316 	base = P2ALIGN(base, (1ul << PA_SLICE_SHIFT));
317 
318 	while (base < end) {
319 		slice_to_memnode[PA_2_SLICE(base)] = mnode;
320 		base += (1ul << PA_SLICE_SHIFT);
321 	}
322 }
323 
324 /*
325  * Dynamically detect memory slices in the system by decoding
326  * the cpu memory decoder registers at boot time.
327  */
328 void
329 plat_fill_mc(pnode_t nodeid)
330 {
331 	uint64_t	mc_addr, saf_addr;
332 	uint64_t	mc_decode[DAK_BANKS_PER_MC];
333 	uint64_t	base, size;
334 	uint64_t	saf_mask;
335 	uint64_t	offset;
336 	uint32_t	regs[4];
337 	int		len;
338 	int		local_mc;
339 	int		portid;
340 	int		boardid;
341 	int		cpuid;
342 	int		i;
343 
344 	if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) ||
345 	    (portid == -1))
346 		return;
347 
348 	/*
349 	 * Decode the board number from the MC portid.  Assumes
350 	 * portid == safari agentid.
351 	 */
352 	boardid = DAK_GETSLOT(portid);
353 	cpuid = DAK_GETSID(portid);
354 
355 	/*
356 	 * The "reg" property returns 4 32-bit values. The first two are
357 	 * combined to form a 64-bit address.  The second two are for a
358 	 * 64-bit size, but we don't actually need to look at that value.
359 	 */
360 	len = prom_getproplen(nodeid, "reg");
361 	if (len != (sizeof (uint32_t) * 4)) {
362 		prom_printf("Warning: malformed 'reg' property\n");
363 		return;
364 	}
365 	if (prom_getprop(nodeid, "reg", (caddr_t)regs) < 0)
366 		return;
367 	mc_addr = ((uint64_t)regs[0]) << 32;
368 	mc_addr |= (uint64_t)regs[1];
369 
370 	/*
371 	 * Figure out whether the memory controller we are examining
372 	 * belongs to this CPU or a different one.
373 	 */
374 	saf_addr = lddsafaddr(8);
375 	saf_mask = (uint64_t)SAF_MASK;
376 	if ((mc_addr & saf_mask) == saf_addr)
377 		local_mc = 1;
378 	else
379 		local_mc = 0;
380 
381 	for (i = 0; i < DAK_BANKS_PER_MC; i++) {
382 		/*
383 		 * Memory decode masks are at offsets 0x10 - 0x28.
384 		 */
385 		offset = 0x10 + (i << 3);
386 
387 		/*
388 		 * If the memory controller is local to this CPU, we use
389 		 * the special ASI to read the decode registers.
390 		 * Otherwise, we load the values from a magic address in
391 		 * I/O space.
392 		 */
393 		if (local_mc)
394 			mc_decode[i] = lddmcdecode(offset);
395 		else
396 			mc_decode[i] = lddphysio(mc_addr | offset);
397 
398 		/*
399 		 * If the upper bit is set, we have a valid mask
400 		 */
401 		if ((int64_t)mc_decode[i] < 0) {
402 			/*
403 			 * The memory decode register is a bitmask field,
404 			 * so we can decode that into both a base and
405 			 * a span.
406 			 */
407 			base = MC_BASE(mc_decode[i]) << PHYS2UM_SHIFT;
408 			size = MC_UK2SPAN(mc_decode[i]);
409 			update_mem_bounds(boardid, cpuid, i, base, size);
410 		}
411 	}
412 }
413 
414 
415 /*
416  * This routine is run midway through the boot process.  By the time we get
417  * here, we know about all the active CPU boards in the system, and we have
418  * extracted information about each board's memory from the memory
419  * controllers.  We have also figured out which ranges of memory will be
420  * assigned to which memnodes, so we walk the slice table to build the table
421  * of memnodes.
422  */
423 /* ARGSUSED */
424 void
425 plat_build_mem_nodes(u_longlong_t *list, size_t  nelems)
426 {
427 	int	slice;
428 	pfn_t   basepfn;
429 	pgcnt_t npgs;
430 
431 	mem_node_pfn_shift = PFN_SLICE_SHIFT;
432 	mem_node_physalign = (1ull << PA_SLICE_SHIFT);
433 	npgs = 1ull << PFN_SLICE_SHIFT;
434 
435 	for (slice = 0; slice < DAK_MAX_SLICE; slice++) {
436 		if (slice_to_memnode[slice] == -1)
437 			continue;
438 		basepfn = (uint64_t)slice << PFN_SLICE_SHIFT;
439 		mem_node_add_slice(basepfn, basepfn + npgs - 1);
440 	}
441 }
442 
443 
444 
445 /*
446  * Daktari support for lgroups.
447  *
448  * On Daktari, an lgroup platform handle == slot number.
449  *
450  * Mappings between lgroup handles and memnodes are managed
451  * in addition to mappings between memory slices and memnodes
452  * to support cross-board interleaving as well as multiple
453  * slices per board (e.g. >1GB DIMMs). The initial mapping
454  * of memnodes to lgroup handles is determined at boot time.
455  */
456 int
457 plat_pfn_to_mem_node(pfn_t pfn)
458 {
459 	return (slice_to_memnode[PFN_2_SLICE(pfn)]);
460 }
461 
462 /*
463  * Return the platform handle for the lgroup containing the given CPU
464  *
465  * For Daktari, lgroup platform handle == slot number
466  */
467 lgrp_handle_t
468 plat_lgrp_cpu_to_hand(processorid_t id)
469 {
470 	return (DAK_GETSLOT(id));
471 }
472 
473 /*
474  * Platform specific lgroup initialization
475  */
476 void
477 plat_lgrp_init(void)
478 {
479 	int i;
480 
481 	/*
482 	 * Initialize lookup tables to invalid values so we catch
483 	 * any illegal use of them.
484 	 */
485 	for (i = 0; i < DAK_MAX_SLICE; i++) {
486 		slice_to_memnode[i] = -1;
487 	}
488 }
489 
490 /*
491  * Return latency between "from" and "to" lgroups
492  *
493  * This latency number can only be used for relative comparison
494  * between lgroups on the running system, cannot be used across platforms,
495  * and may not reflect the actual latency.  It is platform and implementation
496  * specific, so platform gets to decide its value.  It would be nice if the
497  * number was at least proportional to make comparisons more meaningful though.
498  * NOTE: The numbers below are supposed to be load latencies for uncached
499  * memory divided by 10.
500  */
501 int
502 plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to)
503 {
504 	/*
505 	 * Return min remote latency when there are more than two lgroups
506 	 * (root and child) and getting latency between two different lgroups
507 	 * or root is involved
508 	 */
509 	if (lgrp_optimizations() && (from != to ||
510 	    from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE))
511 		return (21);
512 	else
513 		return (19);
514 }
515 /*
516  * No platform drivers on this platform
517  */
518 char *platform_module_list[] = {
519 	(char *)0
520 };
521 
522 /*ARGSUSED*/
523 void
524 plat_tod_fault(enum tod_fault_type tod_bad)
525 {
526 }
527 
528 /*ARGSUSED*/
529 int
530 plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
531     int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
532 {
533 	if (flt_in_memory && (p2get_mem_unum != NULL))
534 		return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
535 			buf, buflen, lenp));
536 	else
537 		return (ENOTSUP);
538 }
539 
540 /*
541  * This platform hook gets called from mc_add_mem_unum_label() in the mc-us3
542  * driver giving each platform the opportunity to add platform
543  * specific label information to the unum for ECC error logging purposes.
544  */
545 void
546 plat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm)
547 {
548 	_NOTE(ARGUNUSED(bank, dimm))
549 
550 	char board = DAK_GETSLOT_LABEL(mcid);
551 	char old_unum[UNUM_NAMLEN];
552 
553 	strcpy(old_unum, unum);
554 	snprintf(unum, UNUM_NAMLEN, "Slot %c: %s", board, old_unum);
555 }
556 
557 int
558 plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
559 {
560 	char board = DAK_GETSLOT_LABEL(cpuid);
561 
562 	if (snprintf(buf, buflen, "Slot %c", board) >= buflen) {
563 		return (ENOSPC);
564 	} else {
565 		*lenp = strlen(buf);
566 		return (0);
567 	}
568 }
569 
570 /*
571  * The zuluvm module requires a dmv interrupt for each installed zulu board.
572  */
573 void
574 plat_dmv_params(uint_t *hwint, uint_t *swint)
575 {
576 	*hwint = 0;
577 	*swint = DAK_SBD_SLOTS - 1;
578 }
579