1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Driver for Intel(R) 10nm server memory controller.
4 * Copyright (c) 2019, Intel Corporation.
5 *
6 */
7
8#include <linux/kernel.h>
9#include <linux/io.h>
10#include <asm/cpu_device_id.h>
11#include <asm/intel-family.h>
12#include <asm/mce.h>
13#include "edac_module.h"
14#include "skx_common.h"
15
16#define I10NM_REVISION	"v0.0.3"
17#define EDAC_MOD_STR	"i10nm_edac"
18
19/* Debug macros */
20#define i10nm_printk(level, fmt, arg...)	\
21	edac_printk(level, "i10nm", fmt, ##arg)
22
23#define I10NM_GET_SCK_BAR(d, reg)	\
24	pci_read_config_dword((d)->uracu, 0xd0, &(reg))
25#define I10NM_GET_IMC_BAR(d, i, reg)	\
26	pci_read_config_dword((d)->uracu, 0xd8 + (i) * 4, &(reg))
27#define I10NM_GET_DIMMMTR(m, i, j)	\
28	readl((m)->mbase + 0x2080c + (i) * 0x4000 + (j) * 4)
29#define I10NM_GET_MCDDRTCFG(m, i)	\
30	readl((m)->mbase + 0x20970 + (i) * 0x4000)
31#define I10NM_GET_MCMTR(m, i)		\
32	readl((m)->mbase + 0x20ef8 + (i) * 0x4000)
33
34#define I10NM_GET_SCK_MMIO_BASE(reg)	(GET_BITFIELD(reg, 0, 28) << 23)
35#define I10NM_GET_IMC_MMIO_OFFSET(reg)	(GET_BITFIELD(reg, 0, 10) << 12)
36#define I10NM_GET_IMC_MMIO_SIZE(reg)	((GET_BITFIELD(reg, 13, 23) - \
37					 GET_BITFIELD(reg, 0, 10) + 1) << 12)
38
39static struct list_head *i10nm_edac_list;
40
41static struct pci_dev *pci_get_dev_wrapper(int dom, unsigned int bus,
42					   unsigned int dev, unsigned int fun)
43{
44	struct pci_dev *pdev;
45
46	pdev = pci_get_domain_bus_and_slot(dom, bus, PCI_DEVFN(dev, fun));
47	if (!pdev) {
48		edac_dbg(2, "No device %02x:%02x.%x\n",
49			 bus, dev, fun);
50		return NULL;
51	}
52
53	if (unlikely(pci_enable_device(pdev) < 0)) {
54		edac_dbg(2, "Failed to enable device %02x:%02x.%x\n",
55			 bus, dev, fun);
56		pci_dev_put(pdev);
57		return NULL;
58	}
59
60	return pdev;
61}
62
63static int i10nm_get_all_munits(void)
64{
65	struct pci_dev *mdev;
66	void __iomem *mbase;
67	unsigned long size;
68	struct skx_dev *d;
69	int i, j = 0;
70	u32 reg, off;
71	u64 base;
72
73	list_for_each_entry(d, i10nm_edac_list, list) {
74		d->util_all = pci_get_dev_wrapper(d->seg, d->bus[1], 29, 1);
75		if (!d->util_all)
76			return -ENODEV;
77
78		d->uracu = pci_get_dev_wrapper(d->seg, d->bus[0], 0, 1);
79		if (!d->uracu)
80			return -ENODEV;
81
82		if (I10NM_GET_SCK_BAR(d, reg)) {
83			i10nm_printk(KERN_ERR, "Failed to socket bar\n");
84			return -ENODEV;
85		}
86
87		base = I10NM_GET_SCK_MMIO_BASE(reg);
88		edac_dbg(2, "socket%d mmio base 0x%llx (reg 0x%x)\n",
89			 j++, base, reg);
90
91		for (i = 0; i < I10NM_NUM_IMC; i++) {
92			mdev = pci_get_dev_wrapper(d->seg, d->bus[0],
93						   12 + i, 0);
94			if (i == 0 && !mdev) {
95				i10nm_printk(KERN_ERR, "No IMC found\n");
96				return -ENODEV;
97			}
98			if (!mdev)
99				continue;
100
101			d->imc[i].mdev = mdev;
102
103			if (I10NM_GET_IMC_BAR(d, i, reg)) {
104				i10nm_printk(KERN_ERR, "Failed to get mc bar\n");
105				return -ENODEV;
106			}
107
108			off  = I10NM_GET_IMC_MMIO_OFFSET(reg);
109			size = I10NM_GET_IMC_MMIO_SIZE(reg);
110			edac_dbg(2, "mc%d mmio base 0x%llx size 0x%lx (reg 0x%x)\n",
111				 i, base + off, size, reg);
112
113			mbase = ioremap(base + off, size);
114			if (!mbase) {
115				i10nm_printk(KERN_ERR, "Failed to ioremap 0x%llx\n",
116					     base + off);
117				return -ENODEV;
118			}
119
120			d->imc[i].mbase = mbase;
121		}
122	}
123
124	return 0;
125}
126
127static struct res_config i10nm_cfg0 = {
128	.type			= I10NM,
129	.decs_did		= 0x3452,
130	.busno_cfg_offset	= 0xcc,
131};
132
133static struct res_config i10nm_cfg1 = {
134	.type			= I10NM,
135	.decs_did		= 0x3452,
136	.busno_cfg_offset	= 0xd0,
137};
138
139static const struct x86_cpu_id i10nm_cpuids[] = {
140	X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ATOM_TREMONT_D,	X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
141	X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ATOM_TREMONT_D,	X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
142	X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X,		X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
143	X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X,		X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
144	X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_D,		X86_STEPPINGS(0x0, 0xf), &i10nm_cfg1),
145	{}
146};
147MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
148
149static bool i10nm_check_ecc(struct skx_imc *imc, int chan)
150{
151	u32 mcmtr;
152
153	mcmtr = I10NM_GET_MCMTR(imc, chan);
154	edac_dbg(1, "ch%d mcmtr reg %x\n", chan, mcmtr);
155
156	return !!GET_BITFIELD(mcmtr, 2, 2);
157}
158
159static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
160{
161	struct skx_pvt *pvt = mci->pvt_info;
162	struct skx_imc *imc = pvt->imc;
163	struct dimm_info *dimm;
164	u32 mtr, mcddrtcfg;
165	int i, j, ndimms;
166
167	for (i = 0; i < I10NM_NUM_CHANNELS; i++) {
168		if (!imc->mbase)
169			continue;
170
171		ndimms = 0;
172		mcddrtcfg = I10NM_GET_MCDDRTCFG(imc, i);
173		for (j = 0; j < I10NM_NUM_DIMMS; j++) {
174			dimm = edac_get_dimm(mci, i, j, 0);
175			mtr = I10NM_GET_DIMMMTR(imc, i, j);
176			edac_dbg(1, "dimmmtr 0x%x mcddrtcfg 0x%x (mc%d ch%d dimm%d)\n",
177				 mtr, mcddrtcfg, imc->mc, i, j);
178
179			if (IS_DIMM_PRESENT(mtr))
180				ndimms += skx_get_dimm_info(mtr, 0, 0, dimm,
181							    imc, i, j);
182			else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
183				ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
184							      EDAC_MOD_STR);
185		}
186		if (ndimms && !i10nm_check_ecc(imc, i)) {
187			i10nm_printk(KERN_ERR, "ECC is disabled on imc %d channel %d\n",
188				     imc->mc, i);
189			return -ENODEV;
190		}
191	}
192
193	return 0;
194}
195
196static struct notifier_block i10nm_mce_dec = {
197	.notifier_call	= skx_mce_check_error,
198	.priority	= MCE_PRIO_EDAC,
199};
200
201#ifdef CONFIG_EDAC_DEBUG
202/*
203 * Debug feature.
204 * Exercise the address decode logic by writing an address to
205 * /sys/kernel/debug/edac/i10nm_test/addr.
206 */
207static struct dentry *i10nm_test;
208
209static int debugfs_u64_set(void *data, u64 val)
210{
211	struct mce m;
212
213	pr_warn_once("Fake error to 0x%llx injected via debugfs\n", val);
214
215	memset(&m, 0, sizeof(m));
216	/* ADDRV + MemRd + Unknown channel */
217	m.status = MCI_STATUS_ADDRV + 0x90;
218	/* One corrected error */
219	m.status |= BIT_ULL(MCI_STATUS_CEC_SHIFT);
220	m.addr = val;
221	skx_mce_check_error(NULL, 0, &m);
222
223	return 0;
224}
225DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n");
226
227static void setup_i10nm_debug(void)
228{
229	i10nm_test = edac_debugfs_create_dir("i10nm_test");
230	if (!i10nm_test)
231		return;
232
233	if (!edac_debugfs_create_file("addr", 0200, i10nm_test,
234				      NULL, &fops_u64_wo)) {
235		debugfs_remove(i10nm_test);
236		i10nm_test = NULL;
237	}
238}
239
240static void teardown_i10nm_debug(void)
241{
242	debugfs_remove_recursive(i10nm_test);
243}
244#else
245static inline void setup_i10nm_debug(void) {}
246static inline void teardown_i10nm_debug(void) {}
247#endif /*CONFIG_EDAC_DEBUG*/
248
249static int __init i10nm_init(void)
250{
251	u8 mc = 0, src_id = 0, node_id = 0;
252	const struct x86_cpu_id *id;
253	struct res_config *cfg;
254	const char *owner;
255	struct skx_dev *d;
256	int rc, i, off[3] = {0xd0, 0xc8, 0xcc};
257	u64 tolm, tohm;
258
259	edac_dbg(2, "\n");
260
261	owner = edac_get_owner();
262	if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
263		return -EBUSY;
264
265	if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
266		return -ENODEV;
267
268	id = x86_match_cpu(i10nm_cpuids);
269	if (!id)
270		return -ENODEV;
271
272	cfg = (struct res_config *)id->driver_data;
273
274	rc = skx_get_hi_lo(0x09a2, off, &tolm, &tohm);
275	if (rc)
276		return rc;
277
278	rc = skx_get_all_bus_mappings(cfg, &i10nm_edac_list);
279	if (rc < 0)
280		goto fail;
281	if (rc == 0) {
282		i10nm_printk(KERN_ERR, "No memory controllers found\n");
283		return -ENODEV;
284	}
285
286	rc = i10nm_get_all_munits();
287	if (rc < 0)
288		goto fail;
289
290	list_for_each_entry(d, i10nm_edac_list, list) {
291		rc = skx_get_src_id(d, 0xf8, &src_id);
292		if (rc < 0)
293			goto fail;
294
295		rc = skx_get_node_id(d, &node_id);
296		if (rc < 0)
297			goto fail;
298
299		edac_dbg(2, "src_id = %d node_id = %d\n", src_id, node_id);
300		for (i = 0; i < I10NM_NUM_IMC; i++) {
301			if (!d->imc[i].mdev)
302				continue;
303
304			d->imc[i].mc  = mc++;
305			d->imc[i].lmc = i;
306			d->imc[i].src_id  = src_id;
307			d->imc[i].node_id = node_id;
308
309			rc = skx_register_mci(&d->imc[i], d->imc[i].mdev,
310					      "Intel_10nm Socket", EDAC_MOD_STR,
311					      i10nm_get_dimm_config);
312			if (rc < 0)
313				goto fail;
314		}
315	}
316
317	rc = skx_adxl_get();
318	if (rc)
319		goto fail;
320
321	opstate_init();
322	mce_register_decode_chain(&i10nm_mce_dec);
323	setup_i10nm_debug();
324
325	i10nm_printk(KERN_INFO, "%s\n", I10NM_REVISION);
326
327	return 0;
328fail:
329	skx_remove();
330	return rc;
331}
332
333static void __exit i10nm_exit(void)
334{
335	edac_dbg(2, "\n");
336	teardown_i10nm_debug();
337	mce_unregister_decode_chain(&i10nm_mce_dec);
338	skx_adxl_put();
339	skx_remove();
340}
341
342module_init(i10nm_init);
343module_exit(i10nm_exit);
344
345MODULE_LICENSE("GPL v2");
346MODULE_DESCRIPTION("MC Driver for Intel 10nm server processors");
347