xref: /illumos-gate/usr/src/uts/sun4u/sunfire/sys/ac.h (revision 29949e86)
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 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_AC_H
28 #define	_SYS_AC_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #ifdef	__cplusplus
33 extern "C" {
34 #endif
35 
36 /* useful debugging stuff */
37 #define	AC_ATTACH_DEBUG		0x1
38 #define	AC_REGISTERS_DEBUG	0x2
39 
40 /*
41  * OBP supplies us with two register sets for the AC nodes. They are:
42  *
43  *	0		miscellaneous regs
44  *	1		Cache tags
45  *
46  * We do not use the cache tags for anything in the kernel, so we
47  * do not map them in.
48  */
49 
50 /* Macros for physical acccess, fhc.h has to be present */
51 #define	AC_OFFSET		0x00001000000ull
52 #define	AC_CENTRAL		0x80000000
53 #define	AC_ARB_FAST		0x00002000
54 #define	AC_BCSR(board)		(FHC_BOARD_BASE(2*(board)) + FHC_OFFSET + \
55 				AC_OFFSET + AC_OFF_BCSR)
56 
57 /* Register set 0 Offsets */
58 #define	AC_OFF_BRCS		0x10
59 #define	AC_OFF_BCSR		0x20
60 #define	AC_OFF_ESR		0x30
61 #define	AC_OFF_EMR		0x40
62 #define	AC_OFF_MEMCTL		0x60
63 #define	AC_OFF_MEMDEC0		0x70
64 #define	AC_OFF_MEMDEC1		0x80
65 #define	AC_OFF_UPA0		0x2000
66 #define	AC_OFF_UPA1		0x4000
67 #define	AC_OFF_CNTR		0x6000
68 #define	AC_OFF_MCCR		0x6020
69 
70 /* Use predefined strings to name the kstats from this driver. */
71 #define	AC_KSTAT_NAME		"address_controller"
72 #define	MEMCTL_KSTAT_NAMED	"acmemctl"
73 #define	MEMDECODE0_KSTAT_NAMED	"acmemdecode0"
74 #define	MEMDECODE1_KSTAT_NAMED	"acmemdecode1"
75 #define	CNTR_KSTAT_NAMED	"accounter"
76 #define	MCCR_KSTAT_NAMED	"acmccr"
77 #define	BANK_0_KSTAT_NAMED	"acbank0"
78 #define	BANK_1_KSTAT_NAMED	"acbank1"
79 
80 /* used for the picN kstats */
81 #define	AC_NUM_PICS	2
82 #define	AC_COUNTER_TO_PIC0(CNTR)	((CNTR) & 0xFFFFFFFFULL)
83 #define	AC_COUNTER_TO_PIC1(CNTR)	((CNTR) >> 32)
84 
85 /* used to clear/set the pcr */
86 #define	AC_CLEAR_PCR(PCR)		((PCR) & ~(0x3F3F))
87 #define	AC_SET_HOT_PLUG(PCR)		((PCR) | (0x3F3F))
88 
89 /* used for programming the pic */
90 #define	AC_SET_PIC_BUS_PAUSE(BRD)	(0x80000000LL - 0x9ac4 - ((BRD) << 3))
91 
92 /* defines for AC Board Configuration and Status Register */
93 #define	NO_CACHE	0
94 #define	CACHE_512K	2
95 #define	CACHE_1M	3
96 #define	CACHE_2M	4
97 #define	CACHE_4M	5
98 #define	CACHE_8M	6
99 #define	CACHE_16M	7
100 
101 #define	ARB_MASTER	0x8000
102 #define	ARB_INIT	0x4000
103 #define	ARB_FAST	0x2000
104 #define	FTC_CPAR	0x0200
105 
106 #define	AC_CSR_REFEN		(1ULL << 27)
107 
108 /* defines for Memory decode registers */
109 #define	AC_MEM_VALID		0x8000000000000000ULL
110 
111 /* size of a memory SIMM group */
112 #define	RASIZE0(memctl)		(8 << ((((memctl) >> 8) & 0x7) << 1))
113 #define	RASIZE1(memctl)		(8 << ((((memctl) >> 11) & 0x7) << 1))
114 #define	RATBL0(memctl)		(((memctl) >> 8) & 0x7)
115 #define	RATBL1(memctl)		(((memctl) >> 11) & 0x7)
116 
117 /*
118  * Interleave factor of a memory SIMM group.
119  * Possible values are 1, 2, 4, 8, and 16. 1 means not interleaved.
120  * Larger groups can be interleaved with smaller groups. Groups
121  * on the same board can be interleaved as well.
122  */
123 #define	INTLV0(memctl)		(1 << ((memctl) & 0x7))
124 #define	INTLV1(memctl)		(1 << (((memctl) >> 3) & 0x7))
125 #define	INTVAL0(memctl)		((memctl) & 0x7)
126 #define	INTVAL1(memctl)		(((memctl) >> 3) & 0x7)
127 
128 /*
129  * Physical base mask of a memory SIMM group. Note that this is
130  * not the real physical base, and is just used to match up the
131  * interleaving of groups. The mask bits (UK) are used to mask
132  * out the match (UM) field so that the bases can be compared.
133  */
134 #define	GRP_UK(memdec)	(((memdec) >> 39) & 0xFFF)
135 #define	GRP_UM(memdec)	(((memdec) >> 12) & 0x7FFF)
136 #define	GRP_BASE(memdec) (GRP_UM(memdec) & ~(GRP_UK(memdec)))
137 #define	GRP_LK(memdec)	(((memdec) >> 6) & 0xf)
138 #define	GRP_LM(memdec)	((memdec) & 0xf)
139 #define	GRP_LBASE(memdec) (GRP_LM(memdec) & ~(GRP_LK(memdec)))
140 #define	GRP_REALBASE(m) ((GRP_BASE(m) << 26) | (GRP_LBASE(m) << 6))
141 #define	GRP_UK2SPAN(memdec) ((GRP_UK(memdec) + 1) << 26)
142 #define	GRP_SPANMB(memdec) (GRP_UK2SPAN(memdec) >> 20)
143 
144 /*
145  * memory states and conditions for sunfire memory system
146  */
147 enum ac_bank_id { Bank0 = 0, Bank1 = 1 };
148 enum ac_bank_status { StUnknown = 0, StNoMem, StBad, StActive, StSpare };
149 enum ac_bank_condition { ConUnknown = 0, ConOK, ConFailing, ConFailed,
150 			ConTest, ConBad };
151 
152 /*
153  * AC memory bank ioctl interface.
154  */
155 
156 /* 'G' (for gigabytes!) does not appear to be used elsewhere in the kernel */
157 #define	AC_IOC		('G'<<8)
158 
159 /*
160  * For all AC_MEM_ ioctls the arg pointer points to a sysc_cfga_cmd_t
161  * except for AC_MEM_ADMIN_VER. The private pointer then points to a
162  * structure of the appropriate type, if required.
163  */
164 #define	AC_MEM_ADMIN_VER	(AC_IOC|0)	/* arg is &ac_mem_version_t */
165 #define	AC_MEM_CONFIGURE	(AC_IOC|1)	/* private == NULL */
166 #define	AC_MEM_UNCONFIGURE	(AC_IOC|2)	/* private == NULL */
167 #define	AC_MEM_STAT		(AC_IOC|3)	/* ac_stat_t */
168 #define	AC_MEM_TEST_START	(AC_IOC|4)	/* ac_mem_test_start_t */
169 #define	AC_MEM_TEST_STOP	(AC_IOC|5)	/* ac_mem_test_stop_t */
170 #define	AC_MEM_TEST_READ	(AC_IOC|6)	/* ac_mem_test_read_t */
171 #define	AC_MEM_TEST_WRITE	(AC_IOC|7)	/* ac_mem_test_write_t */
172 #define	AC_MEM_EXERCISE		(AC_IOC|128)	/* various */
173 
174 #define	AC_OUTPUT_LEN		MAXPATHLEN		/* output str len */
175 
176 typedef enum {
177 	AC_ERR_DEFAULT = 0,	/* generic errors */
178 	AC_ERR_INTRANS,		/* hardware in transition */
179 	AC_ERR_UTHREAD,		/* can't stop user thread */
180 	AC_ERR_KTHREAD,		/* can't stop kernel thread */
181 	AC_ERR_SUSPEND,		/* can't suspend a device */
182 	AC_ERR_RESUME,		/* can't resume a device */
183 	AC_ERR_POWER,		/* not enough power for slot */
184 	AC_ERR_COOLING,		/* not enough cooling for slot */
185 	AC_ERR_PRECHARGE,	/* not enough precharge for slot */
186 	AC_ERR_HOTPLUG,		/* Hot Plug Unavailable */
187 	AC_ERR_HW_COMPAT,	/* incompatible hardware found during dr */
188 	AC_ERR_NON_DR_PROM,	/* prom not support Dynamic Reconfiguration */
189 	AC_ERR_CORE_RESOURCE,	/* core resource cannot be removed */
190 	AC_ERR_PROM,		/* error encountered in OBP/POST */
191 	AC_ERR_DR_INIT,		/* error encountered in sysc_dr_init op */
192 	AC_ERR_NDI_ATTACH,	/* error encountered in NDI attach operations */
193 	AC_ERR_NDI_DETACH,	/* error encountered in NDI detach operations */
194 	AC_ERR_RSTATE,		/* wrong receptacle state */
195 	AC_ERR_OSTATE,		/* wrong occupant state */
196 	AC_ERR_COND,		/* invalid condition */
197 	AC_ERR_BD,		/* invalid board id */
198 	AC_ERR_BD_TYPE,		/* invalid board type */
199 	AC_ERR_BD_STATE,	/* invalid board state */
200 	AC_ERR_MEM_PERM,	/* no write permission */
201 	AC_ERR_MEM_BK,		/* invalid memory bank */
202 	AC_ERR_MEM_TEST,	/* invalid memory test id */
203 	AC_ERR_MEM_TEST_PAR,	/* invalid memory test parameter(s) */
204 	AC_ERR_KPM_CANCELLED,	/* kphysm_del_cancel (for complete) */
205 	AC_ERR_KPM_REFUSED,	/* kphysm_pre_del failed (for complete) */
206 	AC_ERR_KPM_SPAN,	/* memory already in use (add) */
207 	AC_ERR_KPM_DUP,		/* memory span duplicate (delete) */
208 	AC_ERR_KPM_FAULT,	/* memory access test failed (add) */
209 	AC_ERR_KPM_RESOURCE,	/* some resource was not available */
210 	AC_ERR_KPM_NOTSUP,	/* operation not supported */
211 	AC_ERR_KPM_NOHANDLES,	/* cannot allocate any more handles */
212 	AC_ERR_KPM_NONRELOC,	/* non-relocatable pages in span */
213 	AC_ERR_KPM_HANDLE,	/* bad handle supplied */
214 	AC_ERR_KPM_BUSY,	/* memory in span is being deleted */
215 	AC_ERR_KPM_NOTVIABLE,	/* vM viability test failed */
216 	AC_ERR_KPM_SEQUENCE,	/* function called out of sequence */
217 	AC_ERR_KPM_NOWORK,	/* no pages to delete */
218 	AC_ERR_KPM_NOTFINISHED,	/* thread not finished */
219 	AC_ERR_KPM_NOTRUNNING,	/* thread not running */
220 	AC_ERR_VMEM,		/* insufficient virtual memory */
221 	AC_ERR_INTR,		/* delete interrupt by user */
222 	AC_ERR_TIMEOUT,		/* delete timed out */
223 	AC_ERR_MEM_DEINTLV	/* could not de-interleave memory */
224 } ac_err_t;
225 
226 /*
227  * Config admin command structure for AC_MEM ioctls.
228  */
229 typedef struct ac_cfga_cmd {
230 	uint_t		force:1;	/* force this state transition */
231 	uint_t		test:1;		/* Need to test hardware */
232 	int		arg;		/* generic data for test */
233 	ac_err_t	errtype;	/* error code returned */
234 	char		*outputstr;	/* output returned from ioctl */
235 	void		*private;	/* command private data */
236 } ac_cfga_cmd_t;
237 
238 typedef struct ac_cfga_cmd32 {
239 	uint_t		force:1;	/* force this state transition */
240 	uint_t		test:1;		/* Need to test hardware */
241 	int		arg;		/* generic data for test */
242 	ac_err_t	errtype;	/* error code returned */
243 	caddr32_t	outputstr;	/* output returned from ioctl */
244 	caddr32_t	private;	/* command private data */
245 } ac_cfga_cmd32_t;
246 
247 typedef uint_t ac_mem_version_t;		/* platform interface rev */
248 #define	AC_MEM_ADMIN_VERSION	1
249 
250 typedef uint_t mem_test_handle_t;
251 
252 typedef struct {
253 	uint64_t		module_id;
254 	uint64_t		afsr;
255 	uint64_t		afar;
256 	uint64_t		udbh_error_reg;
257 	uint64_t		udbl_error_reg;
258 } sunfire_processor_error_regs_t;
259 
260 /*
261  * page_size gives the requires size for the read or write buffer.
262  * A read can be restricted to one or more line_size units starting
263  * at a multiple of line_size units from the start of the page.
264  * afar_base is the physical base of the bank being tested so
265  * that the afar value can be translated to an offset into the bank.
266  */
267 typedef struct {
268 	mem_test_handle_t	handle;
269 	pid_t			tester_pid;	/* PID of test starter */
270 	sysc_cfga_cond_t	prev_condition;
271 	u_longlong_t		bank_size;	/* bytes */
272 	uint_t			page_size;	/* bytes */
273 	uint_t			line_size;	/* bytes */
274 	u_longlong_t		afar_base;
275 } ac_mem_test_start_t;
276 
277 typedef struct {
278 	mem_test_handle_t	handle;
279 	sysc_cfga_cond_t	condition;
280 } ac_mem_test_stop_t;
281 
282 /*
283  * line_offset is in the range 0 - (page_size/line_size)-1
284  * line_count is in the range 1 - (page_size/line_size)
285  */
286 typedef struct {
287 	u_longlong_t		page_num;
288 	uint_t			line_offset;
289 	uint_t			line_count;
290 } ac_test_addr_t;
291 
292 /*
293  * Data will be transferred in/out of the buffer at:
294  * 		(page_buf + (line_offset*line_size))
295  */
296 typedef struct {
297 	mem_test_handle_t	handle;
298 	void			*page_buf;
299 	ac_test_addr_t		address;
300 	sunfire_processor_error_regs_t	*error_buf;
301 } ac_mem_test_read_t;
302 
303 typedef struct {
304 	mem_test_handle_t	handle;
305 	void			*page_buf;
306 	ac_test_addr_t		address;
307 } ac_mem_test_write_t;
308 
309 #ifdef _SYSCALL32
310 
311 /* Kernel's view of ILP32 structure version. */
312 
313 typedef struct {
314 	mem_test_handle_t	handle;
315 	caddr32_t		page_buf;		/* void * */
316 	ac_test_addr_t		address;
317 	caddr32_t		error_buf; /* sunfire_processor_error_regs_t */
318 } ac_mem_test_read32_t;
319 
320 typedef struct {
321 	mem_test_handle_t	handle;
322 	caddr32_t		page_buf;		/* void * */
323 	ac_test_addr_t		address;
324 } ac_mem_test_write32_t;
325 
326 #endif /* _SYSCALL32 */
327 
328 /* structure returned from AC_MEM_STAT ioctl */
329 typedef struct {
330 	sysc_cfga_rstate_t	rstate;
331 	sysc_cfga_ostate_t	ostate;
332 	sysc_cfga_cond_t	condition;
333 	time_t			status_time;
334 	uint_t			board;
335 	uint_t			real_size;
336 	uint_t			use_size;
337 	uint_t			busy;		/* add/delete in progress */
338 	uint_t			page_size;	/* bytes */
339 	uint64_t		phys_pages;
340 	uint64_t		managed;
341 	uint64_t		nonrelocatable;
342 	/* to supply address, group, info */
343 	uint64_t		ac_memctl;
344 	uint64_t		ac_decode0;
345 	uint64_t		ac_decode1;
346 } ac_stat_t;
347 
348 #ifdef _SYSCALL32
349 
350 /* Kernel's view of ILP32 structure version. */
351 
352 typedef struct {
353 	sysc_cfga_rstate_t	rstate;
354 	sysc_cfga_ostate_t	ostate;
355 	sysc_cfga_cond_t	condition;
356 	time32_t		status_time;
357 	uint_t			board;
358 	uint_t			real_size;
359 	uint_t			use_size;
360 	uint_t			busy;		/* add/delete in progress */
361 	uint_t			page_size;	/* bytes */
362 	uint64_t		phys_pages;
363 	uint64_t		managed;
364 	uint64_t		nonrelocatable;
365 	/* to supply address, group, info */
366 	uint64_t		ac_memctl;
367 	uint64_t		ac_decode0;
368 	uint64_t		ac_decode1;
369 } ac_stat32_t;
370 
371 #endif /* _SYSCALL32 */
372 
373 /* Command values in cmd_cfga.arg for the AC_MEM_EXERCISE ioctl. */
374 #define	AC_MEMX_RELOCATE_ALL	0
375 
376 /* Stats structure for AC_MEMX_RELOCATE_ALL (cmd_cfga.private != NULL). */
377 struct ac_memx_relocate_stats {
378 	uint_t		base;
379 	uint_t		npgs;
380 	uint_t		nopaget;
381 	uint_t		nolock;
382 	uint_t		isfree;
383 	uint_t		reloc;
384 	uint_t		noreloc;
385 };
386 
387 /* End of ioctl interface. */
388 
389 #if defined(_KERNEL)
390 
391 typedef struct {
392 	ac_cfga_cmd_t	cmd_cfga;
393 	char		*errbuf;	/* internal error buffer */
394 	struct ac_soft_state *softsp;
395 	uint_t		bank;		/* Decoded bank number. */
396 } ac_cfga_pkt_t;
397 
398 #define	AC_ERR_SET(pkt, err)	(pkt)->cmd_cfga.errtype = (err)
399 
400 #define	MEM_BOARD_VISIBLE(BD) \
401 		((BD)->sc.rstate == SYSC_CFGA_RSTATE_CONNECTED && \
402 		(BD)->sc.ostate == SYSC_CFGA_OSTATE_CONFIGURED)
403 
404 #ifndef	TRUE
405 #define	TRUE (1)
406 #endif
407 #ifndef	FALSE
408 #define	FALSE (0)
409 #endif
410 
411 #define	AC_BANK0_STATUS		"bank-0-status"
412 #define	AC_BANK1_STATUS		"bank-1-status"
413 #define	AC_BANK_NOMEM		"nomem"
414 #define	AC_BANK_OK		"ok"
415 #define	AC_BANK_SPARE		"spare"
416 #define	AC_BANK_FAILED		"failed"
417 
418 /*
419  * Test for a valid size setting. The size must be set as
420  * a contiguous number of bits starting at the least significant bit.
421  * Adding one to such a number causes a carry to be propagated to
422  * the first zero bit, eg 00111 -> 01000. Thus for a correctly
423  * formed value, the AND of the two numbers is 0.
424  */
425 #define	GRP_SIZE_IS_SET(memdec)	((GRP_UK(memdec) & (GRP_UK(memdec) + 1)) == 0)
426 
427 /* set the decode register bits according to the desired bank layout */
428 #define	SETUP_DECODE(addr, mb, intlv, group) \
429 	((((addr) >> 26) & 0x7fffULL) << 12) |			/* UM */ \
430 	((((mb) >> 6) - 1ULL) << 39) |				/* UK */ \
431 	((group) & 0xfULL) |					/* LM */ \
432 	((0xfULL << (intlv) & 0xfULL) << 6)			/* LK */
433 
434 /*
435  * Driver minor number macros.
436  */
437 #define	AC_GETINSTANCE(M)	((M) >> 1)
438 #define	AC_GETBANK(M)		((M) & 1)
439 #define	AC_PUTINSTANCE(I)	((I) << 1)
440 
441 /*
442  * Attachment point names.
443  */
444 #define	NAME_BANK0	"bank0"
445 #define	NAME_BANK1	"bank1"
446 
447 /*
448  * Memory Database
449  * This information is generally accessed through the bd_list so we will
450  * just protect it by that for now.
451  */
452 struct ac_mem_info {
453 	int busy;				/* A bank is in transition */
454 	time_t status_change;			/* Time of last change */
455 
456 	sysc_cfga_rstate_t rstate;
457 	sysc_cfga_ostate_t ostate;
458 	sysc_cfga_cond_t condition;
459 	uint_t real_size;			/* Real size in MB of bank */
460 	uint_t use_size;			/* In use size in MB */
461 };
462 
463 /* Structures used in the driver to manage the hardware */
464 struct ac_soft_state {
465 	dev_info_t *dip;	/* dev info of myself */
466 	dev_info_t *pdip;	/* dev info of my parent */
467 	int board;		/* Board number for this AC */
468 
469 	/* fields protected by bd_list lock */
470 	struct ac_mem_info bank[2];	/* memory bank information */
471 
472 	/* Mapped addresses of registers */
473 	void *ac_base;		/* Base address of Address Controller */
474 	volatile uint32_t *ac_id;		/* ID register */
475 	volatile uint64_t *ac_memctl;		/* Memory Control */
476 	volatile uint64_t *ac_memdecode0;	/* Memory Decode 0 */
477 	volatile uint64_t *ac_memdecode1;	/* Memory Decode 1 */
478 	volatile uint64_t *ac_counter;		/* AC counter register */
479 	volatile uint32_t *ac_mccr;		/* AC Counter control */
480 	kstat_t *ac_ksp;
481 	kstat_t	*ac_counters_ksp;		/* performance counter kstat */
482 };
483 
484 extern void	ac_blkcopy(caddr_t, caddr_t, uint_t, uint_t);
485 extern void	ac_mapin(uint64_t, caddr_t);
486 extern void	ac_unmap(caddr_t);
487 
488 /* kstat structure used by ac to pass data to user programs. */
489 struct ac_kstat {
490 	struct kstat_named ac_memctl;		/* AC Memory control */
491 	struct kstat_named ac_memdecode0;	/* AC Memory Decode Bank 0 */
492 	struct kstat_named ac_memdecode1;	/* AC Memory Decode Bank 1 */
493 	struct kstat_named ac_mccr;		/* AC Mem Counter Control */
494 	struct kstat_named ac_counter;		/* AC Counter */
495 	struct kstat_named ac_bank0_status;
496 	struct kstat_named ac_bank1_status;
497 };
498 
499 #endif	/* _KERNEL */
500 
501 #ifdef	__cplusplus
502 }
503 #endif
504 
505 #endif	/* _SYS_AC_H */
506