xref: /dragonfly/sys/dev/misc/ecc/e5_imc_var.h (revision 8af44722)
1 #ifndef _E5_IMC_VAR_H_
2 #define _E5_IMC_VAR_H_
3 
4 #define E5_IMC_CHAN_VER2	2	/* E5 v2 */
5 #define E5_IMC_CHAN_VER3	3	/* E5 v3 */
6 
7 struct e5_imc_chan {
8 	uint16_t	did;
9 	int		slot;
10 	int		func;
11 	const char	*desc;
12 
13 	int		chan_ext;	/* external channel */
14 	int		chan;
15 	int		ver;
16 
17 	int		ubox_slot;
18 	int		ubox_func;
19 	uint16_t	ubox_did;
20 
21 	int		cpgc_slot;
22 	int		cpgc_func;
23 	uint16_t	cpgc_did;
24 	uint32_t	cpgc_chandis;
25 
26 	int		ctad_slot;
27 	int		ctad_func;
28 	uint16_t	ctad_did;
29 };
30 
31 #define E5_IMC_CHAN_END	\
32 	{ 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
33 
34 #define E5_IMC_CHAN_FIELDS(v, imc, c, c_ext)			\
35 	.chan_ext	= c_ext,				\
36 	.chan		= c,					\
37 	.ver		= E5_IMC_CHAN_VER##v,			\
38 								\
39 	.ubox_slot	= PCISLOT_E5V##v##_UBOX0,		\
40 	.ubox_func	= PCIFUNC_E5V##v##_UBOX0,		\
41 	.ubox_did	= PCI_E5V##v##_UBOX0_DID_ID,		\
42 								\
43 	.cpgc_slot	= PCISLOT_E5V##v##_IMC##imc##_CPGC,	\
44 	.cpgc_func	= PCIFUNC_E5V##v##_IMC##imc##_CPGC,	\
45 	.cpgc_did	= PCI_E5V##v##_IMC##imc##_CPGC_DID_ID,	\
46 	.cpgc_chandis	= PCI_E5V##v##_IMC_CPGC_MCMTR_CHN_DISABLE(c), \
47 								\
48 	.ctad_slot	= PCISLOT_E5V##v##_IMC##imc##_CTAD,	\
49 	.ctad_func	= PCIFUNC_E5V##v##_IMC##imc##_CTAD(c),	\
50 	.ctad_did	= PCI_E5V##v##_IMC##imc##_CTAD_DID_ID(c) \
51 
52 #define UBOX_READ(dev, c, ofs, w)			\
53 	pcib_read_config((dev), pci_get_bus((dev)),	\
54 	    (c)->ubox_slot, (c)->ubox_func, (ofs), (w))
55 #define UBOX_READ_2(dev, c, ofs)	UBOX_READ((dev), (c), (ofs), 2)
56 #define UBOX_READ_4(dev, c, ofs)	UBOX_READ((dev), (c), (ofs), 4)
57 
58 #define IMC_CPGC_READ(dev, c, ofs, w)			\
59 	pcib_read_config((dev), pci_get_bus((dev)),	\
60 	    (c)->cpgc_slot, (c)->cpgc_func, (ofs), (w))
61 #define IMC_CPGC_READ_2(dev, c, ofs)	IMC_CPGC_READ((dev), (c), (ofs), 2)
62 #define IMC_CPGC_READ_4(dev, c, ofs)	IMC_CPGC_READ((dev), (c), (ofs), 4)
63 
64 #define IMC_CTAD_READ(dev, c, ofs, w)			\
65 	pcib_read_config((dev), pci_get_bus((dev)),	\
66 	    (c)->ctad_slot, (c)->ctad_func, (ofs), (w))
67 #define IMC_CTAD_READ_2(dev, c, ofs)	IMC_CTAD_READ((dev), (c), (ofs), 2)
68 #define IMC_CTAD_READ_4(dev, c, ofs)	IMC_CTAD_READ((dev), (c), (ofs), 4)
69 
70 static __inline int
71 e5_imc_node_probe(device_t dev, const struct e5_imc_chan *c)
72 {
73 	int node, dimm;
74 	uint32_t val;
75 
76 	/* Check CPGC vid/did */
77 	if (IMC_CPGC_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
78 	    IMC_CPGC_READ_2(dev, c, PCIR_DEVICE) != c->cpgc_did)
79 		return -1;
80 
81 	/* Is this channel disabled */
82 	val = IMC_CPGC_READ_4(dev, c, PCI_E5_IMC_CPGC_MCMTR);
83 	if (val & c->cpgc_chandis)
84 		return -1;
85 
86 	/* Check CTAD vid/did */
87 	if (IMC_CTAD_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
88 	    IMC_CTAD_READ_2(dev, c, PCIR_DEVICE) != c->ctad_did)
89 		return -1;
90 
91 	/* Are there any DIMMs populated? */
92 	for (dimm = 0; dimm < PCI_E5_IMC_CHN_DIMM_MAX; ++dimm) {
93 		val = IMC_CTAD_READ_4(dev, c, PCI_E5_IMC_CTAD_DIMMMTR(dimm));
94 		if (val & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP)
95 			break;
96 	}
97 	if (dimm == PCI_E5_IMC_CHN_DIMM_MAX)
98 		return -1;
99 
100 	/* Check UBOX vid/did */
101 	if (UBOX_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
102 	    UBOX_READ_2(dev, c, PCIR_DEVICE) != c->ubox_did)
103 		return -1;
104 
105 	val = UBOX_READ_4(dev, c, PCI_E5_UBOX0_CPUNODEID);
106 	node = __SHIFTOUT(val, PCI_E5_UBOX0_CPUNODEID_LCLNODEID);
107 
108 	return node;
109 }
110 
111 #endif	/* !_E5_IMC_VAR_H_ */
112