i5100_edac.c revision 8f421c595a9145959d8aab09172743132abdffdb
1/*
2 * Intel 5100 Memory Controllers kernel module
3 *
4 * This file may be distributed under the terms of the
5 * GNU General Public License.
6 *
7 * This module is based on the following document:
8 *
9 * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet
10 *      http://download.intel.com/design/chipsets/datashts/318378.pdf
11 *
12 */
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/pci.h>
16#include <linux/pci_ids.h>
17#include <linux/slab.h>
18#include <linux/edac.h>
19#include <linux/delay.h>
20#include <linux/mmzone.h>
21
22#include "edac_core.h"
23
24/* register addresses and bit field accessors... */
25
26/* device 16, func 1 */
27#define I5100_MS		0x44	/* Memory Status Register */
28#define I5100_SPDDATA		0x48	/* Serial Presence Detect Status Reg */
29#define		I5100_SPDDATA_RDO(a)	((a) >> 15 & 1)
30#define		I5100_SPDDATA_SBE(a)	((a) >> 13 & 1)
31#define		I5100_SPDDATA_BUSY(a)	((a) >> 12 & 1)
32#define		I5100_SPDDATA_DATA(a)	((a)       & ((1 << 8) - 1))
33#define I5100_SPDCMD		0x4c	/* Serial Presence Detect Command Reg */
34#define		I5100_SPDCMD_DTI(a)	(((a) & ((1 << 4) - 1)) << 28)
35#define		I5100_SPDCMD_CKOVRD(a)	(((a) & 1)              << 27)
36#define		I5100_SPDCMD_SA(a)	(((a) & ((1 << 3) - 1)) << 24)
37#define		I5100_SPDCMD_BA(a)	(((a) & ((1 << 8) - 1)) << 16)
38#define		I5100_SPDCMD_DATA(a)	(((a) & ((1 << 8) - 1)) <<  8)
39#define		I5100_SPDCMD_CMD(a)	((a) & 1)
40#define I5100_TOLM		0x6c	/* Top of Low Memory */
41#define		I5100_TOLM_TOLM(a)	((a) >> 12 & ((1 << 4) - 1))
42#define I5100_MIR0		0x80	/* Memory Interleave Range 0 */
43#define I5100_MIR1		0x84	/* Memory Interleave Range 1 */
44#define I5100_AMIR_0		0x8c	/* Adjusted Memory Interleave Range 0 */
45#define I5100_AMIR_1		0x90	/* Adjusted Memory Interleave Range 1 */
46#define		I5100_MIR_LIMIT(a)	((a) >> 4 & ((1 << 12) - 1))
47#define		I5100_MIR_WAY1(a)	((a) >> 1 & 1)
48#define		I5100_MIR_WAY0(a)	((a)      & 1)
49#define I5100_FERR_NF_MEM	0xa0	/* MC First Non Fatal Errors */
50#define		I5100_FERR_NF_MEM_CHAN_INDX(a)	((a) >> 28 & 1)
51#define		I5100_FERR_NF_MEM_SPD_MASK	(1 << 18)
52#define		I5100_FERR_NF_MEM_M16ERR_MASK	(1 << 16)
53#define		I5100_FERR_NF_MEM_M15ERR_MASK	(1 << 15)
54#define		I5100_FERR_NF_MEM_M14ERR_MASK	(1 << 14)
55#define		I5100_FERR_NF_MEM_
56#define		I5100_FERR_NF_MEM_
57#define		I5100_FERR_NF_MEM_ANY_MASK	\
58			(I5100_FERR_NF_MEM_M16ERR_MASK | \
59			I5100_FERR_NF_MEM_M15ERR_MASK | \
60			I5100_FERR_NF_MEM_M14ERR_MASK)
61#define		I5100_FERR_NF_MEM_ANY(a)  ((a) & I5100_FERR_NF_MEM_ANY_MASK)
62#define	I5100_NERR_NF_MEM	0xa4	/* MC Next Non-Fatal Errors */
63#define		I5100_NERR_NF_MEM_ANY(a)  I5100_FERR_NF_MEM_ANY(a)
64
65/* device 21 and 22, func 0 */
66#define I5100_MTR_0	0x154	/* Memory Technology Registers 0-3 */
67#define I5100_DMIR	0x15c	/* DIMM Interleave Range */
68#define		I5100_DMIR_LIMIT(a)	((a) >> 16 & ((1 << 11) - 1))
69#define		I5100_DMIR_RANK(a, i)	((a) >> (4 * i) & ((1 <<  2) - 1))
70#define I5100_MTR_4	0x1b0	/* Memory Technology Registers 4,5 */
71#define		I5100_MTR_PRESENT(a)	((a) >> 10 & 1)
72#define		I5100_MTR_ETHROTTLE(a)	((a) >>  9 & 1)
73#define		I5100_MTR_WIDTH(a)	((a) >>  8 & 1)
74#define		I5100_MTR_NUMBANK(a)	((a) >>  6 & 1)
75#define		I5100_MTR_NUMROW(a)	((a) >>  2 & ((1 << 2) - 1))
76#define		I5100_MTR_NUMCOL(a)	((a)       & ((1 << 2) - 1))
77#define	I5100_VALIDLOG	0x18c	/* Valid Log Markers */
78#define		I5100_VALIDLOG_REDMEMVALID(a)	((a) >> 2 & 1)
79#define		I5100_VALIDLOG_RECMEMVALID(a)	((a) >> 1 & 1)
80#define		I5100_VALIDLOG_NRECMEMVALID(a)	((a)      & 1)
81#define	I5100_NRECMEMA	0x190	/* Non-Recoverable Memory Error Log Reg A */
82#define		I5100_NRECMEMA_MERR(a)		((a) >> 15 & ((1 << 5) - 1))
83#define		I5100_NRECMEMA_BANK(a)		((a) >> 12 & ((1 << 3) - 1))
84#define		I5100_NRECMEMA_RANK(a)		((a) >>  8 & ((1 << 3) - 1))
85#define		I5100_NRECMEMA_DM_BUF_ID(a)	((a)       & ((1 << 8) - 1))
86#define	I5100_NRECMEMB	0x194	/* Non-Recoverable Memory Error Log Reg B */
87#define		I5100_NRECMEMB_CAS(a)		((a) >> 16 & ((1 << 13) - 1))
88#define		I5100_NRECMEMB_RAS(a)		((a)       & ((1 << 16) - 1))
89#define	I5100_REDMEMA	0x198	/* Recoverable Memory Data Error Log Reg A */
90#define		I5100_REDMEMA_SYNDROME(a)	(a)
91#define	I5100_REDMEMB	0x19c	/* Recoverable Memory Data Error Log Reg B */
92#define		I5100_REDMEMB_ECC_LOCATOR(a)	((a) & ((1 << 18) - 1))
93#define	I5100_RECMEMA	0x1a0	/* Recoverable Memory Error Log Reg A */
94#define		I5100_RECMEMA_MERR(a)		I5100_NRECMEMA_MERR(a)
95#define		I5100_RECMEMA_BANK(a)		I5100_NRECMEMA_BANK(a)
96#define		I5100_RECMEMA_RANK(a)		I5100_NRECMEMA_RANK(a)
97#define		I5100_RECMEMA_DM_BUF_ID(a)	I5100_NRECMEMA_DM_BUF_ID(a)
98#define	I5100_RECMEMB	0x1a4	/* Recoverable Memory Error Log Reg B */
99#define		I5100_RECMEMB_CAS(a)		I5100_NRECMEMB_CAS(a)
100#define		I5100_RECMEMB_RAS(a)		I5100_NRECMEMB_RAS(a)
101
102/* some generic limits */
103#define I5100_MAX_RANKS_PER_CTLR	6
104#define I5100_MAX_CTLRS			2
105#define I5100_MAX_RANKS_PER_DIMM	4
106#define I5100_DIMM_ADDR_LINES		(6 - 3)	/* 64 bits / 8 bits per byte */
107#define I5100_MAX_DIMM_SLOTS_PER_CTLR	4
108#define I5100_MAX_RANK_INTERLEAVE	4
109#define I5100_MAX_DMIRS			5
110
111struct i5100_priv {
112	/* ranks on each dimm -- 0 maps to not present -- obtained via SPD */
113	int dimm_numrank[I5100_MAX_CTLRS][I5100_MAX_DIMM_SLOTS_PER_CTLR];
114
115	/*
116	 * mainboard chip select map -- maps i5100 chip selects to
117	 * DIMM slot chip selects.  In the case of only 4 ranks per
118	 * controller, the mapping is fairly obvious but not unique.
119	 * we map -1 -> NC and assume both controllers use the same
120	 * map...
121	 *
122	 */
123	int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CTLR][I5100_MAX_RANKS_PER_DIMM];
124
125	/* memory interleave range */
126	struct {
127		u64	 limit;
128		unsigned way[2];
129	} mir[I5100_MAX_CTLRS];
130
131	/* adjusted memory interleave range register */
132	unsigned amir[I5100_MAX_CTLRS];
133
134	/* dimm interleave range */
135	struct {
136		unsigned rank[I5100_MAX_RANK_INTERLEAVE];
137		u64	 limit;
138	} dmir[I5100_MAX_CTLRS][I5100_MAX_DMIRS];
139
140	/* memory technology registers... */
141	struct {
142		unsigned present;	/* 0 or 1 */
143		unsigned ethrottle;	/* 0 or 1 */
144		unsigned width;		/* 4 or 8 bits  */
145		unsigned numbank;	/* 2 or 3 lines */
146		unsigned numrow;	/* 13 .. 16 lines */
147		unsigned numcol;	/* 11 .. 12 lines */
148	} mtr[I5100_MAX_CTLRS][I5100_MAX_RANKS_PER_CTLR];
149
150	u64 tolm;		/* top of low memory in bytes */
151	unsigned ranksperctlr;	/* number of ranks per controller */
152
153	struct pci_dev *mc;	/* device 16 func 1 */
154	struct pci_dev *ch0mm;	/* device 21 func 0 */
155	struct pci_dev *ch1mm;	/* device 22 func 0 */
156};
157
158/* map a rank/ctlr to a slot number on the mainboard */
159static int i5100_rank_to_slot(const struct mem_ctl_info *mci,
160			      int ctlr, int rank)
161{
162	const struct i5100_priv *priv = mci->pvt_info;
163	int i;
164
165	for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
166		int j;
167		const int numrank = priv->dimm_numrank[ctlr][i];
168
169		for (j = 0; j < numrank; j++)
170			if (priv->dimm_csmap[i][j] == rank)
171				return i * 2 + ctlr;
172	}
173
174	return -1;
175}
176
177/*
178 * The processor bus memory addresses are broken into three
179 * pieces, whereas the controller addresses are contiguous.
180 *
181 * here we map from the controller address space to the
182 * processor address space:
183 *
184 *    Processor Address Space
185 * +-----------------------------+
186 * |                             |
187 * |  "high" memory addresses    |
188 * |                             |
189 * +-----------------------------+ <- 4GB on the i5100
190 * |                             |
191 * |  other non-memory addresses |
192 * |                             |
193 * +-----------------------------+ <- top of low memory
194 * |                             |
195 * | "low" memory addresses      |
196 * |                             |
197 * +-----------------------------+
198 */
199static unsigned long i5100_ctl_page_to_phys(struct mem_ctl_info *mci,
200					    unsigned long cntlr_addr)
201{
202	const struct i5100_priv *priv = mci->pvt_info;
203
204	if (cntlr_addr < priv->tolm)
205		return cntlr_addr;
206
207	return (1ULL << 32) + (cntlr_addr - priv->tolm);
208}
209
210static const char *i5100_err_msg(unsigned err)
211{
212	const char *merrs[] = {
213		"unknown", /* 0 */
214		"uncorrectable data ECC on replay", /* 1 */
215		"unknown", /* 2 */
216		"unknown", /* 3 */
217		"aliased uncorrectable demand data ECC", /* 4 */
218		"aliased uncorrectable spare-copy data ECC", /* 5 */
219		"aliased uncorrectable patrol data ECC", /* 6 */
220		"unknown", /* 7 */
221		"unknown", /* 8 */
222		"unknown", /* 9 */
223		"non-aliased uncorrectable demand data ECC", /* 10 */
224		"non-aliased uncorrectable spare-copy data ECC", /* 11 */
225		"non-aliased uncorrectable patrol data ECC", /* 12 */
226		"unknown", /* 13 */
227		"correctable demand data ECC", /* 14 */
228		"correctable spare-copy data ECC", /* 15 */
229		"correctable patrol data ECC", /* 16 */
230		"unknown", /* 17 */
231		"SPD protocol error", /* 18 */
232		"unknown", /* 19 */
233		"spare copy initiated", /* 20 */
234		"spare copy completed", /* 21 */
235	};
236	unsigned i;
237
238	for (i = 0; i < ARRAY_SIZE(merrs); i++)
239		if (1 << i & err)
240			return merrs[i];
241
242	return "none";
243}
244
245/* convert csrow index into a rank (per controller -- 0..5) */
246static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)
247{
248	const struct i5100_priv *priv = mci->pvt_info;
249
250	return csrow % priv->ranksperctlr;
251}
252
253/* convert csrow index into a controller (0..1) */
254static int i5100_csrow_to_cntlr(const struct mem_ctl_info *mci, int csrow)
255{
256	const struct i5100_priv *priv = mci->pvt_info;
257
258	return csrow / priv->ranksperctlr;
259}
260
261static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci,
262				    int ctlr, int rank)
263{
264	const struct i5100_priv *priv = mci->pvt_info;
265
266	return ctlr * priv->ranksperctlr + rank;
267}
268
269static void i5100_handle_ce(struct mem_ctl_info *mci,
270			    int ctlr,
271			    unsigned bank,
272			    unsigned rank,
273			    unsigned long syndrome,
274			    unsigned cas,
275			    unsigned ras,
276			    const char *msg)
277{
278	const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
279
280	printk(KERN_ERR
281		"CE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
282		"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
283		ctlr, bank, rank, syndrome, cas, ras,
284		csrow, mci->csrows[csrow].channels[0].label, msg);
285
286	mci->ce_count++;
287	mci->csrows[csrow].ce_count++;
288	mci->csrows[csrow].channels[0].ce_count++;
289}
290
291static void i5100_handle_ue(struct mem_ctl_info *mci,
292			    int ctlr,
293			    unsigned bank,
294			    unsigned rank,
295			    unsigned long syndrome,
296			    unsigned cas,
297			    unsigned ras,
298			    const char *msg)
299{
300	const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
301
302	printk(KERN_ERR
303		"UE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
304		"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
305		ctlr, bank, rank, syndrome, cas, ras,
306		csrow, mci->csrows[csrow].channels[0].label, msg);
307
308	mci->ue_count++;
309	mci->csrows[csrow].ue_count++;
310}
311
312static void i5100_read_log(struct mem_ctl_info *mci, int ctlr,
313			   u32 ferr, u32 nerr)
314{
315	struct i5100_priv *priv = mci->pvt_info;
316	struct pci_dev *pdev = (ctlr) ? priv->ch1mm : priv->ch0mm;
317	u32 dw;
318	u32 dw2;
319	unsigned syndrome = 0;
320	unsigned ecc_loc = 0;
321	unsigned merr;
322	unsigned bank;
323	unsigned rank;
324	unsigned cas;
325	unsigned ras;
326
327	pci_read_config_dword(pdev, I5100_VALIDLOG, &dw);
328
329	if (I5100_VALIDLOG_REDMEMVALID(dw)) {
330		pci_read_config_dword(pdev, I5100_REDMEMA, &dw2);
331		syndrome = I5100_REDMEMA_SYNDROME(dw2);
332		pci_read_config_dword(pdev, I5100_REDMEMB, &dw2);
333		ecc_loc = I5100_REDMEMB_ECC_LOCATOR(dw2);
334	}
335
336	if (I5100_VALIDLOG_RECMEMVALID(dw)) {
337		const char *msg;
338
339		pci_read_config_dword(pdev, I5100_RECMEMA, &dw2);
340		merr = I5100_RECMEMA_MERR(dw2);
341		bank = I5100_RECMEMA_BANK(dw2);
342		rank = I5100_RECMEMA_RANK(dw2);
343
344		pci_read_config_dword(pdev, I5100_RECMEMB, &dw2);
345		cas = I5100_RECMEMB_CAS(dw2);
346		ras = I5100_RECMEMB_RAS(dw2);
347
348		/* FIXME:  not really sure if this is what merr is...
349		 */
350		if (!merr)
351			msg = i5100_err_msg(ferr);
352		else
353			msg = i5100_err_msg(nerr);
354
355		i5100_handle_ce(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
356	}
357
358	if (I5100_VALIDLOG_NRECMEMVALID(dw)) {
359		const char *msg;
360
361		pci_read_config_dword(pdev, I5100_NRECMEMA, &dw2);
362		merr = I5100_NRECMEMA_MERR(dw2);
363		bank = I5100_NRECMEMA_BANK(dw2);
364		rank = I5100_NRECMEMA_RANK(dw2);
365
366		pci_read_config_dword(pdev, I5100_NRECMEMB, &dw2);
367		cas = I5100_NRECMEMB_CAS(dw2);
368		ras = I5100_NRECMEMB_RAS(dw2);
369
370		/* FIXME:  not really sure if this is what merr is...
371		 */
372		if (!merr)
373			msg = i5100_err_msg(ferr);
374		else
375			msg = i5100_err_msg(nerr);
376
377		i5100_handle_ue(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
378	}
379
380	pci_write_config_dword(pdev, I5100_VALIDLOG, dw);
381}
382
383static void i5100_check_error(struct mem_ctl_info *mci)
384{
385	struct i5100_priv *priv = mci->pvt_info;
386	u32 dw;
387
388
389	pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw);
390	if (I5100_FERR_NF_MEM_ANY(dw)) {
391		u32 dw2;
392
393		pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2);
394		if (dw2)
395			pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM,
396					       dw2);
397		pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
398
399		i5100_read_log(mci, I5100_FERR_NF_MEM_CHAN_INDX(dw),
400			       I5100_FERR_NF_MEM_ANY(dw),
401			       I5100_NERR_NF_MEM_ANY(dw2));
402	}
403}
404
405static struct pci_dev *pci_get_device_func(unsigned vendor,
406					   unsigned device,
407					   unsigned func)
408{
409	struct pci_dev *ret = NULL;
410
411	while (1) {
412		ret = pci_get_device(vendor, device, ret);
413
414		if (!ret)
415			break;
416
417		if (PCI_FUNC(ret->devfn) == func)
418			break;
419	}
420
421	return ret;
422}
423
424static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci,
425					    int csrow)
426{
427	struct i5100_priv *priv = mci->pvt_info;
428	const unsigned ctlr_rank = i5100_csrow_to_rank(mci, csrow);
429	const unsigned ctlr = i5100_csrow_to_cntlr(mci, csrow);
430	unsigned addr_lines;
431
432	/* dimm present? */
433	if (!priv->mtr[ctlr][ctlr_rank].present)
434		return 0ULL;
435
436	addr_lines =
437		I5100_DIMM_ADDR_LINES +
438		priv->mtr[ctlr][ctlr_rank].numcol +
439		priv->mtr[ctlr][ctlr_rank].numrow +
440		priv->mtr[ctlr][ctlr_rank].numbank;
441
442	return (unsigned long)
443		((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE);
444}
445
446static void __devinit i5100_init_mtr(struct mem_ctl_info *mci)
447{
448	struct i5100_priv *priv = mci->pvt_info;
449	struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
450	int i;
451
452	for (i = 0; i < I5100_MAX_CTLRS; i++) {
453		int j;
454		struct pci_dev *pdev = mms[i];
455
456		for (j = 0; j < I5100_MAX_RANKS_PER_CTLR; j++) {
457			const unsigned addr =
458				(j < 4) ? I5100_MTR_0 + j * 2 :
459					  I5100_MTR_4 + (j - 4) * 2;
460			u16 w;
461
462			pci_read_config_word(pdev, addr, &w);
463
464			priv->mtr[i][j].present = I5100_MTR_PRESENT(w);
465			priv->mtr[i][j].ethrottle = I5100_MTR_ETHROTTLE(w);
466			priv->mtr[i][j].width = 4 + 4 * I5100_MTR_WIDTH(w);
467			priv->mtr[i][j].numbank = 2 + I5100_MTR_NUMBANK(w);
468			priv->mtr[i][j].numrow = 13 + I5100_MTR_NUMROW(w);
469			priv->mtr[i][j].numcol = 10 + I5100_MTR_NUMCOL(w);
470		}
471	}
472}
473
474/*
475 * FIXME: make this into a real i2c adapter (so that dimm-decode
476 * will work)?
477 */
478static int i5100_read_spd_byte(const struct mem_ctl_info *mci,
479			       u8 ch, u8 slot, u8 addr, u8 *byte)
480{
481	struct i5100_priv *priv = mci->pvt_info;
482	u16 w;
483	u32 dw;
484	unsigned long et;
485
486	pci_read_config_word(priv->mc, I5100_SPDDATA, &w);
487	if (I5100_SPDDATA_BUSY(w))
488		return -1;
489
490	dw =	I5100_SPDCMD_DTI(0xa) |
491		I5100_SPDCMD_CKOVRD(1) |
492		I5100_SPDCMD_SA(ch * 4 + slot) |
493		I5100_SPDCMD_BA(addr) |
494		I5100_SPDCMD_DATA(0) |
495		I5100_SPDCMD_CMD(0);
496	pci_write_config_dword(priv->mc, I5100_SPDCMD, dw);
497
498	/* wait up to 100ms */
499	et = jiffies + HZ / 10;
500	udelay(100);
501	while (1) {
502		pci_read_config_word(priv->mc, I5100_SPDDATA, &w);
503		if (!I5100_SPDDATA_BUSY(w))
504			break;
505		udelay(100);
506	}
507
508	if (!I5100_SPDDATA_RDO(w) || I5100_SPDDATA_SBE(w))
509		return -1;
510
511	*byte = I5100_SPDDATA_DATA(w);
512
513	return 0;
514}
515
516/*
517 * fill dimm chip select map
518 *
519 * FIXME:
520 *   o only valid for 4 ranks per controller
521 *   o not the only way to may chip selects to dimm slots
522 *   o investigate if there is some way to obtain this map from the bios
523 */
524static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci)
525{
526	struct i5100_priv *priv = mci->pvt_info;
527	int i;
528
529	WARN_ON(priv->ranksperctlr != 4);
530
531	for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
532		int j;
533
534		for (j = 0; j < I5100_MAX_RANKS_PER_DIMM; j++)
535			priv->dimm_csmap[i][j] = -1; /* default NC */
536	}
537
538	/* only 2 chip selects per slot... */
539	priv->dimm_csmap[0][0] = 0;
540	priv->dimm_csmap[0][1] = 3;
541	priv->dimm_csmap[1][0] = 1;
542	priv->dimm_csmap[1][1] = 2;
543	priv->dimm_csmap[2][0] = 2;
544	priv->dimm_csmap[3][0] = 3;
545}
546
547static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
548					     struct mem_ctl_info *mci)
549{
550	struct i5100_priv *priv = mci->pvt_info;
551	int i;
552
553	for (i = 0; i < I5100_MAX_CTLRS; i++) {
554		int j;
555
556		for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CTLR; j++) {
557			u8 rank;
558
559			if (i5100_read_spd_byte(mci, i, j, 5, &rank) < 0)
560				priv->dimm_numrank[i][j] = 0;
561			else
562				priv->dimm_numrank[i][j] = (rank & 3) + 1;
563		}
564	}
565
566	i5100_init_dimm_csmap(mci);
567}
568
569static void __devinit i5100_init_interleaving(struct pci_dev *pdev,
570					      struct mem_ctl_info *mci)
571{
572	u16 w;
573	u32 dw;
574	struct i5100_priv *priv = mci->pvt_info;
575	struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
576	int i;
577
578	pci_read_config_word(pdev, I5100_TOLM, &w);
579	priv->tolm = (u64) I5100_TOLM_TOLM(w) * 256 * 1024 * 1024;
580
581	pci_read_config_word(pdev, I5100_MIR0, &w);
582	priv->mir[0].limit = (u64) I5100_MIR_LIMIT(w) << 28;
583	priv->mir[0].way[1] = I5100_MIR_WAY1(w);
584	priv->mir[0].way[0] = I5100_MIR_WAY0(w);
585
586	pci_read_config_word(pdev, I5100_MIR1, &w);
587	priv->mir[1].limit = (u64) I5100_MIR_LIMIT(w) << 28;
588	priv->mir[1].way[1] = I5100_MIR_WAY1(w);
589	priv->mir[1].way[0] = I5100_MIR_WAY0(w);
590
591	pci_read_config_word(pdev, I5100_AMIR_0, &w);
592	priv->amir[0] = w;
593	pci_read_config_word(pdev, I5100_AMIR_1, &w);
594	priv->amir[1] = w;
595
596	for (i = 0; i < I5100_MAX_CTLRS; i++) {
597		int j;
598
599		for (j = 0; j < 5; j++) {
600			int k;
601
602			pci_read_config_dword(mms[i], I5100_DMIR + j * 4, &dw);
603
604			priv->dmir[i][j].limit =
605				(u64) I5100_DMIR_LIMIT(dw) << 28;
606			for (k = 0; k < I5100_MAX_RANKS_PER_DIMM; k++)
607				priv->dmir[i][j].rank[k] =
608					I5100_DMIR_RANK(dw, k);
609		}
610	}
611
612	i5100_init_mtr(mci);
613}
614
615static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
616{
617	int i;
618	unsigned long total_pages = 0UL;
619	struct i5100_priv *priv = mci->pvt_info;
620
621	for (i = 0; i < mci->nr_csrows; i++) {
622		const unsigned long npages = i5100_npages(mci, i);
623		const unsigned cntlr = i5100_csrow_to_cntlr(mci, i);
624		const unsigned rank = i5100_csrow_to_rank(mci, i);
625
626		if (!npages)
627			continue;
628
629		/*
630		 * FIXME: these two are totally bogus -- I don't see how to
631		 * map them correctly to this structure...
632		 */
633		mci->csrows[i].first_page = total_pages;
634		mci->csrows[i].last_page = total_pages + npages - 1;
635		mci->csrows[i].page_mask = 0UL;
636
637		mci->csrows[i].nr_pages = npages;
638		mci->csrows[i].grain = 32;
639		mci->csrows[i].csrow_idx = i;
640		mci->csrows[i].dtype =
641			(priv->mtr[cntlr][rank].width == 4) ? DEV_X4 : DEV_X8;
642		mci->csrows[i].ue_count = 0;
643		mci->csrows[i].ce_count = 0;
644		mci->csrows[i].mtype = MEM_RDDR2;
645		mci->csrows[i].edac_mode = EDAC_SECDED;
646		mci->csrows[i].mci = mci;
647		mci->csrows[i].nr_channels = 1;
648		mci->csrows[i].channels[0].chan_idx = 0;
649		mci->csrows[i].channels[0].ce_count = 0;
650		mci->csrows[i].channels[0].csrow = mci->csrows + i;
651		snprintf(mci->csrows[i].channels[0].label,
652			 sizeof(mci->csrows[i].channels[0].label),
653			 "DIMM%u", i5100_rank_to_slot(mci, cntlr, rank));
654
655		total_pages += npages;
656	}
657}
658
659static int __devinit i5100_init_one(struct pci_dev *pdev,
660				    const struct pci_device_id *id)
661{
662	int rc;
663	struct mem_ctl_info *mci;
664	struct i5100_priv *priv;
665	struct pci_dev *ch0mm, *ch1mm;
666	int ret = 0;
667	u32 dw;
668	int ranksperch;
669
670	if (PCI_FUNC(pdev->devfn) != 1)
671		return -ENODEV;
672
673	rc = pci_enable_device(pdev);
674	if (rc < 0) {
675		ret = rc;
676		goto bail;
677	}
678
679	/* figure out how many ranks, from strapped state of 48GB_Mode input */
680	pci_read_config_dword(pdev, I5100_MS, &dw);
681	ranksperch = !!(dw & (1 << 8)) * 2 + 4;
682
683	if (ranksperch != 4) {
684		/* FIXME: get 6 ranks / controller to work - need hw... */
685		printk(KERN_INFO "i5100_edac: unsupported configuration.\n");
686		ret = -ENODEV;
687		goto bail;
688	}
689
690	/* device 21, func 0, Channel 0 Memory Map, Error Flag/Mask, etc... */
691	ch0mm = pci_get_device_func(PCI_VENDOR_ID_INTEL,
692				    PCI_DEVICE_ID_INTEL_5100_21, 0);
693	if (!ch0mm)
694		return -ENODEV;
695
696	rc = pci_enable_device(ch0mm);
697	if (rc < 0) {
698		ret = rc;
699		goto bail_ch0;
700	}
701
702	/* device 22, func 0, Channel 1 Memory Map, Error Flag/Mask, etc... */
703	ch1mm = pci_get_device_func(PCI_VENDOR_ID_INTEL,
704				    PCI_DEVICE_ID_INTEL_5100_22, 0);
705	if (!ch1mm) {
706		ret = -ENODEV;
707		goto bail_ch0;
708	}
709
710	rc = pci_enable_device(ch1mm);
711	if (rc < 0) {
712		ret = rc;
713		goto bail_ch1;
714	}
715
716	mci = edac_mc_alloc(sizeof(*priv), ranksperch * 2, 1, 0);
717	if (!mci) {
718		ret = -ENOMEM;
719		goto bail_ch1;
720	}
721
722	mci->dev = &pdev->dev;
723
724	priv = mci->pvt_info;
725	priv->ranksperctlr = ranksperch;
726	priv->mc = pdev;
727	priv->ch0mm = ch0mm;
728	priv->ch1mm = ch1mm;
729
730	i5100_init_dimm_layout(pdev, mci);
731	i5100_init_interleaving(pdev, mci);
732
733	mci->mtype_cap = MEM_FLAG_FB_DDR2;
734	mci->edac_ctl_cap = EDAC_FLAG_SECDED;
735	mci->edac_cap = EDAC_FLAG_SECDED;
736	mci->mod_name = "i5100_edac.c";
737	mci->mod_ver = "not versioned";
738	mci->ctl_name = "i5100";
739	mci->dev_name = pci_name(pdev);
740	mci->ctl_page_to_phys = i5100_ctl_page_to_phys;
741
742	mci->edac_check = i5100_check_error;
743
744	i5100_init_csrows(mci);
745
746	/* this strange construction seems to be in every driver, dunno why */
747	switch (edac_op_state) {
748	case EDAC_OPSTATE_POLL:
749	case EDAC_OPSTATE_NMI:
750		break;
751	default:
752		edac_op_state = EDAC_OPSTATE_POLL;
753		break;
754	}
755
756	if (edac_mc_add_mc(mci)) {
757		ret = -ENODEV;
758		goto bail_mc;
759	}
760
761	goto bail;
762
763bail_mc:
764	edac_mc_free(mci);
765
766bail_ch1:
767	pci_dev_put(ch1mm);
768
769bail_ch0:
770	pci_dev_put(ch0mm);
771
772bail:
773	return ret;
774}
775
776static void __devexit i5100_remove_one(struct pci_dev *pdev)
777{
778	struct mem_ctl_info *mci;
779	struct i5100_priv *priv;
780
781	mci = edac_mc_del_mc(&pdev->dev);
782
783	if (!mci)
784		return;
785
786	priv = mci->pvt_info;
787	pci_dev_put(priv->ch0mm);
788	pci_dev_put(priv->ch1mm);
789
790	edac_mc_free(mci);
791}
792
793static const struct pci_device_id i5100_pci_tbl[] __devinitdata = {
794	/* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */
795	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) },
796	{ 0, }
797};
798MODULE_DEVICE_TABLE(pci, i5100_pci_tbl);
799
800static struct pci_driver i5100_driver = {
801	.name = KBUILD_BASENAME,
802	.probe = i5100_init_one,
803	.remove = __devexit_p(i5100_remove_one),
804	.id_table = i5100_pci_tbl,
805};
806
807static int __init i5100_init(void)
808{
809	int pci_rc;
810
811	pci_rc = pci_register_driver(&i5100_driver);
812
813	return (pci_rc < 0) ? pci_rc : 0;
814}
815
816static void __exit i5100_exit(void)
817{
818	pci_unregister_driver(&i5100_driver);
819}
820
821module_init(i5100_init);
822module_exit(i5100_exit);
823
824MODULE_LICENSE("GPL");
825MODULE_AUTHOR
826    ("Arthur Jones <ajones@riverbed.com>");
827MODULE_DESCRIPTION("MC Driver for Intel I5100 memory controllers");
828