xref: /illumos-gate/usr/src/uts/intel/io/amdzen/amdzen.h (revision 8af575c0afc1d79bd23c3e1a78a546c9963e5083)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2020 Oxide Computer Company
14  */
15 
16 #ifndef _AMDZEN_H
17 #define	_AMDZEN_H
18 
19 #include <sys/ddi.h>
20 #include <sys/sunddi.h>
21 #include <sys/list.h>
22 #include <sys/pci.h>
23 #include <sys/taskq.h>
24 #include <sys/bitmap.h>
25 
26 /*
27  * This header describes properties of the data fabric and our internal state
28  * for the Zen Nexus driver.
29  */
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /*
36  * The data fabric devices are always defined to be on PCI bus zero starting at
37  * device 0x18.
38  */
39 #define	AMDZEN_DF_BUSNO		0x00
40 #define	AMDZEN_DF_FIRST_DEVICE	0x18
41 
42 /*
43  * The maximum amount of Data Fabric node's we can see. In Zen 1 there were up
44  * to four per package.
45  */
46 #define	AMDZEN_MAX_DFS		0x8
47 
48 /*
49  * The maximum number of PCI functions we expect to encounter on the data
50  * fabric.
51  */
52 #define	AMDZEN_MAX_DF_FUNCS	0x8
53 
54 
55 /*
56  * Registers in the data fabric space that we care about for the purposes of the
57  * nexus driver understanding itself.
58  */
59 
60 /*
61  * This set of registers provides us access to the count of instances in the
62  * data fabric and then a number of different pieces of information about them
63  * like their type. Note, these registers require indirect access because the
64  * information cannot be broadcast.
65  */
66 #define	AMDZEN_DF_F0_FBICNT	0x40
67 #define	AMDZEN_DF_F0_FBICNT_COUNT(x)	BITX(x, 7, 0)
68 #define	AMDZEN_DF_F0_FBIINFO0	0x44
69 #define	AMDZEN_DF_F0_FBIINFO0_TYPE(x)		BITX(x, 3, 0)
70 typedef enum {
71 	AMDZEN_DF_TYPE_CCM = 0,
72 	AMDZEN_DF_TYPE_GCM,
73 	AMDZEN_DF_TYPE_NCM,
74 	AMDZEN_DF_TYPE_IOMS,
75 	AMDZEN_DF_TYPE_CS,
76 	AMDZEN_DF_TYPE_TCDX,
77 	AMDZEN_DF_TYPE_PIE,
78 	AMDZEN_DF_TYPE_SPF,
79 	AMDZEN_DF_TYPE_LLC,
80 	AMDZEN_DF_TYPE_CAKE
81 } amdzen_df_type_t;
82 #define	AMDZEN_DF_F0_FBIINFO0_SDP_WIDTH(x)	BITX(x, 5, 4)
83 typedef enum {
84 	AMDZEN_DF_SDP_W_64 = 0,
85 	AMDZEN_DF_SDP_W_128,
86 	AMDZEN_DF_SDP_W_256,
87 	AMDZEN_DF_SDP_W_512
88 } amdzen_df_sdp_width_t;
89 #define	AMDZEN_DF_F0_FBIINFO0_ENABLED(x)	BITX(x, 6, 6)
90 #define	AMDZEN_DF_F0_FBIINFO0_FTI_WIDTH(x)	BITX(x, 9, 8)
91 typedef enum {
92 	AMDZEN_DF_FTI_W_64 = 0,
93 	AMDZEN_DF_FTI_W_128,
94 	AMDZEN_DF_FTI_W_256,
95 	AMDZEN_DF_FTI_W_512
96 } amdzen_df_fti_width_t;
97 #define	AMDZEN_DF_F0_FBIINFO0_SDP_PCOUNT(x)	BITX(x, 13, 12)
98 #define	AMDZEN_DF_F0_FBIINFO0_FTI_PCOUNT(x)	BITX(x, 18, 16)
99 #define	AMDZEN_DF_F0_FBIINFO0_HAS_MCA(x)	BITX(x, 23, 23)
100 #define	AMDZEN_DF_F0_FBIINFO0_SUBTYPE(x)	BITX(x, 26, 24)
101 #define	AMDZEN_DF_SUBTYPE_NONE	0
102 typedef enum {
103 	AMDZEN_DF_CAKE_SUBTYPE_GMI = 1,
104 	AMDZEN_DF_CAKE_SUBTYPE_xGMI = 2
105 } amdzen_df_cake_subtype_t;
106 
107 typedef enum {
108 	AMDZEN_DF_IOM_SUBTYPE_IOHUB = 1,
109 } amdzen_df_iom_subtype_t;
110 
111 typedef enum {
112 	AMDZEN_DF_CS_SUBTYPE_UMC = 1,
113 	AMDZEN_DF_CS_SUBTYPE_CCIX = 2
114 } amdzen_df_cs_subtype_t;
115 
116 #define	AMDZEN_DF_F0_FBIINFO1	0x48
117 #define	AMDZEN_DF_F0_FBIINFO1_FTI0_NINSTID(x)	BITX(x, 7, 0)
118 #define	AMDZEN_DF_F0_FBIINFO1_FTI1_NINSTID(x)	BITX(x, 15, 8)
119 #define	AMDZEN_DF_F0_FBIINFO1_FTI2_NINSTID(x)	BITX(x, 23, 16)
120 #define	AMDZEN_DF_F0_FBIINFO1_FTI3_NINSTID(x)	BITX(x, 31, 24)
121 #define	AMDZEN_DF_F0_FBIINFO2	0x4c
122 #define	AMDZEN_DF_F0_FBIINFO2_FTI4_NINSTID(x)	BITX(x, 7, 0)
123 #define	AMDZEN_DF_F0_FBIINFO2_FTI5_NINSTID(x)	BITX(x, 15, 8)
124 #define	AMDZEN_DF_F0_FBIINFO3	0x50
125 #define	AMDZEN_DF_F0_FBIINFO3_INSTID(x)		BITX(x, 7, 0)
126 #define	AMDZEN_DF_F0_FBIINFO3_FABID(x)		BITX(x, 13, 8)
127 
128 /*
129  * This register contains the information about the configuration of PCIe buses.
130  * We care about finding which one has our BUS A, which is required to map it to
131  * the northbridge.
132  */
133 #define	AMDZEN_DF_F0_CFG_ADDR_CTL	0x84
134 #define	AMDZEN_DF_F0_CFG_ADDR_CTL_BUS_NUM(x)	BITX(x, 7, 0)
135 
136 /*
137  * Registers that describe how the system is actually put together.
138  */
139 #define	AMDZEN_DF_F1_SYSCFG	0x200
140 #define	AMDZEN_DF_F1_SYSCFG_DIE_PRESENT(X)	BITX(x, 7, 0)
141 #define	AMDZEN_DF_F1_SYSCFG_DIE_TYPE(x)		BITX(x, 18, 11)
142 #define	AMDZEN_DF_F1_SYSCFG_MYDIE_TYPE(x)	BITX(x, 24, 23)
143 typedef enum {
144 	AMDZEN_DF_DIE_TYPE_CPU	= 0,
145 	AMDZEN_DF_DIE_TYPE_APU,
146 	AMDZEN_DF_DIE_TYPE_dGPU
147 } amdzen_df_die_type_t;
148 #define	AMDZEN_DF_F1_SYSCFG_OTHERDIE_TYPE(x)	BITX(x, 26, 25)
149 #define	AMDZEN_DF_F1_SYSCFG_OTHERSOCK(x)	BITX(x, 27, 27)
150 #define	AMDZEN_DF_F1_SYSCFG_NODEID(x)		BITX(x, 30, 28)
151 
152 #define	AMDZEN_DF_F1_FIDMASK0	0x208
153 #define	AMDZEN_DF_F1_FIDMASK0_COMP_MASK(x)	BITX(x, 9, 0)
154 #define	AMDZEN_DF_F1_FIDMASK0_NODE_MASK(x)	BITX(x, 25, 16)
155 #define	AMDZEN_DF_F1_FIDMASK1	0x20C
156 #define	AMDZEN_DF_F1_FIDMASK1_NODE_SHIFT(x)	BITX(x, 3, 0)
157 #define	AMDZEN_DF_F1_FIDMASK1_SKT_SHIFT(x)	BITX(x, 9, 8)
158 #define	AMDZEN_DF_F1_FIDMASK1_DIE_MASK(x)	BITX(x, 18, 16)
159 #define	AMDZEN_DF_F1_FIDMASK1_SKT_MASK(x)	BITX(x, 26, 24)
160 
161 /*
162  * These two registers define information about the PSP and SMU on local and
163  * remote dies (from the context of the DF instance). The bits are the same.
164  */
165 #define	AMDZEN_DF_F1_PSPSMU_LOCAL	0x268
166 #define	AMDZEN_DF_F1_PSPSMU_REMOTE	0x268
167 #define	AMDZEN_DF_F1_PSPSMU_SMU_VALID(x)	BITX(x, 0, 0)
168 #define	AMDZEN_DF_F1_PSPSMU_SMU_UNITID(x)	BITX(x, 6, 1)
169 #define	AMDZEN_DF_F1_PSPSMU_SMU_COMPID(x)	BITX(x, 15, 8)
170 #define	AMDZEN_DF_F1_PSPSMU_PSP_VALID(x)	BITX(x, 16, 16)
171 #define	AMDZEN_DF_F1_PSPSMU_PSP_UNITID(x)	BITX(x, 22, 17)
172 #define	AMDZEN_DF_F1_PSPSMU_PSP_COMPID(x)	BITX(x, 31, 24)
173 
174 #define	AMDZEN_DF_F1_CAKE_ENCR		0x2cc
175 
176 /*
177  * These registers are used to define Indirect Access, commonly known as FICAA
178  * and FICAD for the system. While there are multiple copies of the indirect
179  * access registers in device 4, we're only allowed access to one set of those
180  * (which are the ones present here). Specifically the OS is given access to set
181  * 3.
182  */
183 #define	AMDZEN_DF_F4_FICAA	0x5c
184 #define	AMDZEN_DF_F4_FICAA_TARG_INST	(1 << 0)
185 #define	AMDZEN_DF_F4_FICAA_SET_REG(x)	((x) & 0x3fc)
186 #define	AMDZEN_DF_F4_FICAA_SET_FUNC(x)	(((x) & 0x7) << 11)
187 #define	AMDZEN_DF_F4_FICAA_SET_64B	(1 << 14)
188 #define	AMDZEN_DF_F4_FICAA_SET_INST(x)	(((x) & 0xff) << 16)
189 #define	AMDZEN_DF_F4_FICAD_LO	0x98
190 #define	AMDZEN_DF_F4_FICAD_HI	0x9c
191 
192 /*
193  * Northbridge registers that are relevant for the nexus, mostly for SMN.
194  */
195 #define	AMDZEN_NB_SMN_ADDR	0x60
196 #define	AMDZEN_NB_SMN_DATA	0x64
197 
198 /*
199  * AMD PCI ID for reference
200  */
201 #define	AMDZEN_PCI_VID_AMD	0x1022
202 
203 typedef enum {
204 	AMDZEN_STUB_TYPE_DF,
205 	AMDZEN_STUB_TYPE_NB
206 } amdzen_stub_type_t;
207 
208 typedef struct {
209 	list_node_t		azns_link;
210 	dev_info_t		*azns_dip;
211 	uint16_t		azns_vid;
212 	uint16_t		azns_did;
213 	uint16_t		azns_bus;
214 	uint16_t		azns_dev;
215 	uint16_t		azns_func;
216 	ddi_acc_handle_t	azns_cfgspace;
217 } amdzen_stub_t;
218 
219 typedef enum  {
220 	AMDZEN_DFE_F_MCA	= 1 << 0,
221 	AMDZEN_DFE_F_ENABLED	= 1 << 1
222 } amdzen_df_ent_flags_t;
223 
224 typedef struct {
225 	uint8_t adfe_drvid;
226 	amdzen_df_ent_flags_t adfe_flags;
227 	amdzen_df_type_t adfe_type;
228 	uint8_t adfe_subtype;
229 	uint8_t adfe_fabric_id;
230 	uint8_t adfe_inst_id;
231 	amdzen_df_sdp_width_t adfe_sdp_width;
232 	amdzen_df_fti_width_t adfe_fti_width;
233 	uint8_t adfe_sdp_count;
234 	uint8_t adfe_fti_count;
235 	uint32_t adfe_info0;
236 	uint32_t adfe_info1;
237 	uint32_t adfe_info2;
238 	uint32_t adfe_info3;
239 	uint32_t adfe_syscfg;
240 	uint32_t adfe_mask0;
241 	uint32_t adfe_mask1;
242 } amdzen_df_ent_t;
243 
244 typedef enum {
245 	AMDZEN_DF_F_VALID		= 1 << 0,
246 	AMDZEN_DF_F_FOUND_NB		= 1 << 1
247 } amdzen_df_flags_t;
248 
249 typedef struct {
250 	amdzen_df_flags_t	adf_flags;
251 	uint_t		adf_nb_busno;
252 	amdzen_stub_t	*adf_funcs[AMDZEN_MAX_DF_FUNCS];
253 	amdzen_stub_t	*adf_nb;
254 	uint_t		adf_nents;
255 	amdzen_df_ent_t	*adf_ents;
256 	uint32_t	adf_nodeid;
257 	uint32_t	adf_syscfg;
258 	uint32_t	adf_mask0;
259 	uint32_t	adf_mask1;
260 } amdzen_df_t;
261 
262 typedef enum {
263 	AMDZEN_F_UNSUPPORTED		= 1 << 0,
264 	AMDZEN_F_DEVICE_ERROR		= 1 << 1,
265 	AMDZEN_F_MAP_ERROR		= 1 << 2,
266 	AMDZEN_F_SCAN_DISPATCHED	= 1 << 3,
267 	AMDZEN_F_SCAN_COMPLETE		= 1 << 4,
268 	AMDZEN_F_ATTACH_DISPATCHED	= 1 << 5,
269 	AMDZEN_F_ATTACH_COMPLETE	= 1 << 6
270 } amdzen_flags_t;
271 
272 #define	AMDZEN_F_TASKQ_MASK	(AMDZEN_F_SCAN_DISPATCHED | \
273     AMDZEN_F_SCAN_COMPLETE | AMDZEN_F_ATTACH_DISPATCHED | \
274     AMDZEN_F_ATTACH_COMPLETE)
275 
276 typedef struct amdzen {
277 	kmutex_t	azn_mutex;
278 	kcondvar_t	azn_cv;
279 	amdzen_flags_t	azn_flags;
280 	dev_info_t	*azn_dip;
281 	taskqid_t	azn_taskqid;
282 	uint_t		azn_nscanned;
283 	uint_t		azn_npresent;
284 	list_t		azn_df_stubs;
285 	list_t		azn_nb_stubs;
286 	uint_t		azn_ndfs;
287 	amdzen_df_t	azn_dfs[AMDZEN_MAX_DFS];
288 } amdzen_t;
289 
290 typedef enum {
291 	AMDZEN_C_SMNTEMP = 1,
292 	AMDZEN_C_USMN,
293 	AMDZEN_C_ZEN_UDF
294 } amdzen_child_t;
295 
296 /*
297  * Functions for stubs.
298  */
299 extern int amdzen_attach_stub(dev_info_t *, ddi_attach_cmd_t);
300 extern int amdzen_detach_stub(dev_info_t *, ddi_detach_cmd_t);
301 
302 #ifdef __cplusplus
303 }
304 #endif
305 
306 #endif /* _AMDZEN_H */
307