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 _MCAMD_API_H
28 #define	_MCAMD_API_H
29 
30 /*
31  * Primary header file for mcamd_* routines in $SRC/common/mc.  The
32  * routines not implemented there are required to be implemented in the
33  * kernel or userland consumer of this interface (such as the mc-amd driver).
34  * The common code must use the wrapper functions provided by the consumer
35  * to navigate the MC tree, get properties etc.
36  */
37 
38 #if defined(_KERNEL)
39 #include <sys/systm.h>
40 #include <sys/sunddi.h>
41 #else
42 #include <string.h>
43 #include <assert.h>
44 #endif
45 
46 #include <sys/types.h>
47 #include <sys/mc.h>
48 #include <sys/mca_amd.h>
49 #include <sys/mc_amd.h>
50 
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54 
55 /*
56  * Consumers of this common code must implement the following types.
57  */
58 typedef struct mcamd_node mcamd_node_t;
59 struct mcamd_hdl;
60 
61 /*
62  * Properties and raw register values for an mcamd_node_t are retrieved via
63  * mcamd_get_numprop(s) and mcamd_get_cfgreg(s) specifying a property or
64  * register code below.
65  */
66 
67 typedef uint64_t mcamd_prop_t;
68 typedef uint32_t mcamd_cfgreg_t;
69 
70 typedef enum mcamd_propcode {
71 	/*
72 	 * Common properties
73 	 */
74 	MCAMD_PROP_NUM = 0x4000,
75 #define	MCAMD_PROPSTR_NUM		"num"
76 	MCAMD_PROP_SIZE,
77 #define	MCAMD_PROPSTR_SIZE		"size"
78 	MCAMD_PROP_BASE_ADDR,
79 #define	MCAMD_PROPSTR_BASE_ADDR		"base-addr"
80 	/*
81 	 * Memory controller properties
82 	 */
83 	MCAMD_PROP_REV = 0x5000,
84 #define	MCAMD_PROPSTR_REV		"revision"
85 	MCAMD_PROP_LIM_ADDR,
86 #define	MCAMD_PROPSTR_LIM_ADDR		"lim-addr"
87 	MCAMD_PROP_ILEN,
88 #define	MCAMD_PROPSTR_ILEN		"node-ilen"
89 	MCAMD_PROP_ILSEL,
90 #define	MCAMD_PROPSTR_ILSEL		"node-ilsel"
91 	MCAMD_PROP_CSINTLVFCTR,
92 #define	MCAMD_PROPSTR_CSINTLVFCTR	"cs-intlv-factor"
93 	MCAMD_PROP_DRAMHOLE_SIZE,
94 #define	MCAMD_PROPSTR_DRAMHOLE_SIZE	"dram-hole-size"
95 	MCAMD_PROP_ACCESS_WIDTH,
96 #define	MCAMD_PROPSTR_ACCESS_WIDTH	"access-width"
97 	MCAMD_PROP_CSBANKMAPREG,
98 #define	MCAMD_PROPSTR_CSBANKMAPREG	"bank-mapping"
99 	MCAMD_PROP_BANKSWZL,
100 #define	MCAMD_PROPSTR_BANKSWZL		"bankswizzle"
101 	MCAMD_PROP_MOD64MUX,
102 #define	MCAMD_PROPSTR_MOD64MUX		"mismatched-dimm-support"
103 	MCAMD_PROP_SPARECS,
104 #define	MCAMD_PROPSTR_SPARECS		"spare-csnum"
105 	MCAMD_PROP_BADCS,
106 #define	MCAMD_PROPSTR_BADCS		"bad-csnum"
107 	/*
108 	 * Chip-select properties
109 	 */
110 	MCAMD_PROP_MASK = 0x6000,
111 #define	MCAMD_PROPSTR_MASK		"mask"
112 	MCAMD_PROP_CSBE,
113 #define	MCAMD_PROPSTR_CSBE		"cs-bank-enable"
114 	MCAMD_PROP_SPARE,
115 #define	MCAMD_PROPSTR_SPARE		"online-spare"
116 	MCAMD_PROP_TESTFAIL,
117 #define	MCAMD_PROPSTR_TESTFAIL		"failed-test"
118 	MCAMD_PROP_CSDIMM1,
119 #define	MCAMD_PROPSTR_CSDIMM1		"dimm1-num"
120 	MCAMD_PROP_CSDIMM2,
121 #define	MCAMD_PROPSTR_CSDIMM2		"dimm2-num"
122 	MCAMD_PROP_DIMMRANK
123 #define	MCAMD_PROPSTR_DIMMRANK		"dimm-rank"
124 } mcamd_propcode_t;
125 
126 typedef enum mcamd_regcode {
127 	MCAMD_REG_DRAMBASE = 0x7000,
128 	MCAMD_REG_DRAMLIMIT,
129 	MCAMD_REG_DRAMHOLE,
130 	MCAMD_REG_DRAMCFGLO,
131 	MCAMD_REG_DRAMCFGHI,
132 	MCAMD_REG_CSBASE,
133 	MCAMD_REG_CSMASK
134 } mcamd_regcode_t;
135 /*
136  * Flags for mcamd_dprintf
137  */
138 #define	MCAMD_DBG_ERR		0x1
139 #define	MCAMD_DBG_FLOW		0x2
140 
141 typedef union mcamd_dimm_offset_un mcamd_dimm_offset_un_t;
142 
143 /*
144  * Offset definition.  Encode everything in a single uint64_t, allowing some
145  * room for growth in numbers of rows/columns/banks in future MC revisions.
146  * Some consumers will handle this as an opaque uint64 to be passed around,
147  * while others will want to look inside via the union defined below.  Since
148  * we must support a 32-bit kernel we structure this as two uint32_t.
149  */
150 
151 #define	MCAMD_OFFSET_VERSION_0			0x0
152 #define	MCAMD_OFFSET_VERSION			MCAMD_OFFSET_VERSION_0
153 
154 union mcamd_dimm_offset_un {
155 	uint64_t _dou_offset;
156 	struct {
157 		struct {
158 			uint32_t dou_col:20;	/* column address */
159 			uint32_t dou_bank:4;	/* internal sdram bank number */
160 			uint32_t unused:8;
161 		} lo;
162 		struct {
163 			uint32_t dou_row:20;	/* row address */
164 			uint32_t dou_rank:3;	/* cs rank on dimm */
165 			uint32_t unused:4;
166 			uint32_t dou_version:4;	/* offset encoding version */
167 			uint32_t dou_valid:1;	/* set if valid */
168 		} hi;
169 	} _dou_hilo;
170 };
171 
172 #define	do_offset  _dou_offset
173 
174 #define	do_valid _dou_hilo.hi.dou_valid
175 #define	do_version _dou_hilo.hi.dou_version
176 #define	do_rank _dou_hilo.hi.dou_rank
177 #define	do_row _dou_hilo.hi.dou_row
178 #define	do_bank _dou_hilo.lo.dou_bank
179 #define	do_col _dou_hilo.lo.dou_col
180 
181 /*
182  * The following work on an offset treated as a uint64_t.
183  */
184 #define	MCAMD_RC_OFFSET_VALID(offset) (((uint64_t)(offset) & (1ULL << 63)) != 0)
185 #define	MCAMD_RC_OFFSET_VERSION(offset) (((uint64_t)offset >> 59) & 0xf)
186 
187 /*
188  * Value to be used to indicate an invalid offset.
189  */
190 #define	MCAMD_RC_INVALID_OFFSET 0x0
191 
192 /*
193  * Routines provided by the common mcamd code.
194  */
195 extern const char *mcamd_get_propname(mcamd_propcode_t);
196 
197 extern int mcamd_patounum(struct mcamd_hdl *, mcamd_node_t *, uint64_t,
198     uint8_t, uint8_t, uint32_t, int, mc_unum_t *);
199 extern int mcamd_unumtopa(struct mcamd_hdl *, mcamd_node_t *, mc_unum_t *,
200     uint64_t *);
201 extern int mc_pa_to_offset(struct mcamd_hdl *, mcamd_node_t *, mcamd_node_t *,
202     uint64_t, uint64_t *);
203 extern int mc_offset_to_pa(struct mcamd_hdl *, mcamd_node_t *, mcamd_node_t *,
204     uint64_t, uint64_t *);
205 
206 extern int mcamd_cs_size(struct mcamd_hdl *, mcamd_node_t *, int, size_t *);
207 
208 extern int mcamd_synd_validate(struct mcamd_hdl *, uint32_t, int);
209 extern int mcamd_eccsynd_decode(struct mcamd_hdl *, uint32_t, uint_t *);
210 extern int mcamd_cksynd_decode(struct mcamd_hdl *, uint32_t, uint_t *,
211     uint_t *);
212 extern int mcamd_cksym_decode(struct mcamd_hdl *, uint_t, int *, int *,
213     int *, int *);
214 
215 extern void *mcamd_set_errno_ptr(struct mcamd_hdl *, int);
216 extern const char *mcamd_strerror(int);
217 extern const char *mcamd_errmsg(struct mcamd_hdl *);
218 
219 /*
220  * Routines to be provided by wrapper code.
221  */
222 extern mcamd_node_t *mcamd_mc_next(struct mcamd_hdl *, mcamd_node_t *,
223     mcamd_node_t *);
224 extern mcamd_node_t *mcamd_cs_next(struct mcamd_hdl *, mcamd_node_t *,
225     mcamd_node_t *);
226 extern mcamd_node_t *mcamd_dimm_next(struct mcamd_hdl *, mcamd_node_t *,
227     mcamd_node_t *);
228 
229 extern mcamd_node_t *mcamd_cs_mc(struct mcamd_hdl *, mcamd_node_t *);
230 extern mcamd_node_t *mcamd_dimm_mc(struct mcamd_hdl *, mcamd_node_t *);
231 
232 extern int mcamd_get_numprop(struct mcamd_hdl *, mcamd_node_t *,
233     mcamd_propcode_t, mcamd_prop_t *);
234 extern int mcamd_get_numprops(struct mcamd_hdl *, ...);
235 extern int mcamd_get_cfgreg(struct mcamd_hdl *, mcamd_node_t *,
236     mcamd_regcode_t, mcamd_cfgreg_t *);
237 extern int mcamd_get_cfgregs(struct mcamd_hdl *, ...);
238 
239 extern int mcamd_errno(struct mcamd_hdl *);
240 extern int mcamd_set_errno(struct mcamd_hdl *, int);
241 extern void mcamd_dprintf(struct mcamd_hdl *, int, const char *, ...);
242 
243 #ifdef __cplusplus
244 }
245 #endif
246 
247 #endif /* _MCAMD_API_H */
248