10 #include <linux/module.h>
12 #include <linux/pci.h>
20 #define I3200_REVISION "1.1"
22 #define EDAC_MOD_STR "i3200_edac"
24 #define PCI_DEVICE_ID_INTEL_3200_HB 0x29f0
28 #define I3200_RANKS_PER_CHANNEL 4
29 #define I3200_CHANNELS 2
33 #define I3200_MCHBAR_LOW 0x48
34 #define I3200_MCHBAR_HIGH 0x4c
35 #define I3200_MCHBAR_MASK 0xfffffc000ULL
36 #define I3200_MMR_WINDOW_SIZE 16384
38 #define I3200_TOM 0xa0
43 #define I3200_TOM_MASK 0x3ff
44 #define I3200_TOM_SHIFT 26
46 #define I3200_ERRSTS 0xc8
64 #define I3200_ERRSTS_UE 0x0002
65 #define I3200_ERRSTS_CE 0x0001
66 #define I3200_ERRSTS_BITS (I3200_ERRSTS_UE | I3200_ERRSTS_CE)
71 #define I3200_C0DRB 0x200
76 #define I3200_C1DRB 0x600
77 #define I3200_DRB_MASK 0x3ff
78 #define I3200_DRB_SHIFT 26
80 #define I3200_C0ECCERRLOG 0x280
92 #define I3200_C1ECCERRLOG 0x680
93 #define I3200_ECCERRLOG_CE 0x1
94 #define I3200_ECCERRLOG_UE 0x2
95 #define I3200_ECCERRLOG_RANK_BITS 0x18000000
96 #define I3200_ECCERRLOG_RANK_SHIFT 27
97 #define I3200_ECCERRLOG_SYNDROME_BITS 0xff0000
98 #define I3200_ECCERRLOG_SYNDROME_SHIFT 16
99 #define I3200_CAPID0 0xe0
105 static int nr_channels;
107 static int how_many_channels(
struct pci_dev *pdev)
109 unsigned char capid0_8b;
111 pci_read_config_byte(pdev,
I3200_CAPID0 + 8, &capid0_8b);
112 if (capid0_8b & 0x20) {
113 edac_dbg(0,
"In single channel mode\n");
116 edac_dbg(0,
"In dual channel mode\n");
121 static unsigned long eccerrlog_syndrome(
u64 log)
127 static int eccerrlog_row(
int channel,
u64 log)
154 static struct pci_dev *mci_pdev;
155 static int i3200_registered = 1;
191 if (nr_channels == 2)
204 if (nr_channels == 2)
208 i3200_clear_error_info(mci);
211 static void i3200_process_error_info(
struct mem_ctl_info *mci,
222 -1, -1, -1,
"UE overwrote CE",
"");
226 for (channel = 0; channel < nr_channels; channel++) {
231 eccerrlog_row(channel, log),
236 0, 0, eccerrlog_syndrome(log),
237 eccerrlog_row(channel, log),
249 i3200_get_and_clear_error_info(mci, &info);
250 i3200_process_error_info(mci, &info);
271 "i3200: mmio space beyond accessible range (0x%llx)\n",
272 (
unsigned long long)
u.mchbar);
279 (
unsigned long long)
u.mchbar);
285 static void i3200_get_drbs(
void __iomem *window,
296 static bool i3200_is_stacked(
struct pci_dev *pdev,
301 pci_read_config_word(pdev,
I3200_TOM, &tom);
304 return drbs[
I3200_CHANNELS - 1][I3200_RANKS_PER_CHANNEL - 1] == tom;
307 static unsigned long drb_to_nr_pages(
309 int channel,
int rank)
316 if (stacked && (channel == 1) &&
317 drbs[channel][rank] == drbs[channel][I3200_RANKS_PER_CHANNEL - 1])
318 n -= drbs[0][I3200_RANKS_PER_CHANNEL - 1];
324 static int i3200_probe1(
struct pci_dev *pdev,
int dev_idx)
341 i3200_get_drbs(window, drbs);
342 nr_channels = how_many_channels(pdev);
346 layers[0].is_virt_csrow =
true;
348 layers[1].size = nr_channels;
349 layers[1].is_virt_csrow =
false;
372 stacked = i3200_is_stacked(pdev, drbs);
381 unsigned long nr_pages;
384 nr_pages = drb_to_nr_pages(drbs, stacked,
385 i / I3200_RANKS_PER_CHANNEL,
386 i % I3200_RANKS_PER_CHANNEL);
402 i3200_clear_error_info(mci);
406 edac_dbg(3,
"MC: failed edac_mc_add_mc()\n");
469 .probe = i3200_init_one,
471 .id_table = i3200_pci_tbl,
474 static int __init i3200_init(
void)
483 pci_rc = pci_register_driver(&i3200_driver);
488 i3200_registered = 0;
492 edac_dbg(0,
"i3200 pci_get_device fail\n");
497 pci_rc = i3200_init_one(mci_pdev, i3200_pci_tbl);
517 static void __exit i3200_exit(
void)
522 if (!i3200_registered) {
523 i3200_remove_one(mci_pdev);