diff options
| -rw-r--r-- | drivers/edac/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/edac/Makefile | 1 | ||||
| -rw-r--r-- | drivers/edac/i7300_edac.c | 1373 | ||||
| -rw-r--r-- | include/linux/pci_ids.h | 19 |
4 files changed, 1392 insertions, 8 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 70bb350de99..4573ccc11f9 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
| @@ -199,6 +199,13 @@ config EDAC_I5100 | |||
| 199 | Support for error detection and correction the Intel | 199 | Support for error detection and correction the Intel |
| 200 | San Clemente MCH. | 200 | San Clemente MCH. |
| 201 | 201 | ||
| 202 | config EDAC_I7300 | ||
| 203 | tristate "Intel Clarksboro MCH" | ||
| 204 | depends on EDAC_MM_EDAC && X86 && PCI | ||
| 205 | help | ||
| 206 | Support for error detection and correction the Intel | ||
| 207 | Clarksboro MCH (Intel 7300 chipset). | ||
| 208 | |||
| 202 | config EDAC_MPC85XX | 209 | config EDAC_MPC85XX |
| 203 | tristate "Freescale MPC83xx / MPC85xx" | 210 | tristate "Freescale MPC83xx / MPC85xx" |
| 204 | depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx) | 211 | depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx) |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index ca6b1bb24cc..bca4369d6b7 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
| @@ -24,6 +24,7 @@ obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o | |||
| 24 | obj-$(CONFIG_EDAC_I5000) += i5000_edac.o | 24 | obj-$(CONFIG_EDAC_I5000) += i5000_edac.o |
| 25 | obj-$(CONFIG_EDAC_I5100) += i5100_edac.o | 25 | obj-$(CONFIG_EDAC_I5100) += i5100_edac.o |
| 26 | obj-$(CONFIG_EDAC_I5400) += i5400_edac.o | 26 | obj-$(CONFIG_EDAC_I5400) += i5400_edac.o |
| 27 | obj-$(CONFIG_EDAC_I7300) += i7300_edac.o | ||
| 27 | obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o | 28 | obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o |
| 28 | obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o | 29 | obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o |
| 29 | obj-$(CONFIG_EDAC_E752X) += e752x_edac.o | 30 | obj-$(CONFIG_EDAC_E752X) += e752x_edac.o |
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c new file mode 100644 index 00000000000..eb3f30e96ee --- /dev/null +++ b/drivers/edac/i7300_edac.c | |||
| @@ -0,0 +1,1373 @@ | |||
| 1 | /* | ||
| 2 | * Intel 7300 class Memory Controllers kernel module (Clarksboro) | ||
| 3 | * | ||
| 4 | * This file may be distributed under the terms of the | ||
| 5 | * GNU General Public License version 2 only. | ||
| 6 | * | ||
| 7 | * Copyright (c) 2010 by: | ||
| 8 | * Mauro Carvalho Chehab <mchehab@redhat.com> | ||
| 9 | * | ||
| 10 | * Red Hat Inc. http://www.redhat.com | ||
| 11 | * | ||
| 12 | * Intel 7300 Chipset Memory Controller Hub (MCH) - Datasheet | ||
| 13 | * http://www.intel.com/Assets/PDF/datasheet/318082.pdf | ||
| 14 | * | ||
| 15 | * TODO: The chipset allow checking for PCI Express errors also. Currently, | ||
| 16 | * the driver covers only memory error errors | ||
| 17 | * | ||
| 18 | * This driver uses "csrows" EDAC attribute to represent DIMM slot# | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/pci.h> | ||
| 24 | #include <linux/pci_ids.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/edac.h> | ||
| 27 | #include <linux/mmzone.h> | ||
| 28 | |||
| 29 | #include "edac_core.h" | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Alter this version for the I7300 module when modifications are made | ||
| 33 | */ | ||
| 34 | #define I7300_REVISION " Ver: 1.0.0 " __DATE__ | ||
| 35 | |||
| 36 | #define EDAC_MOD_STR "i7300_edac" | ||
| 37 | |||
| 38 | #define i7300_printk(level, fmt, arg...) \ | ||
| 39 | edac_printk(level, "i7300", fmt, ##arg) | ||
| 40 | |||
| 41 | #define i7300_mc_printk(mci, level, fmt, arg...) \ | ||
| 42 | edac_mc_chipset_printk(mci, level, "i7300", fmt, ##arg) | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Memory topology is organized as: | ||
| 46 | * Branch 0 - 2 channels: channels 0 and 1 (FDB0 PCI dev 21.0) | ||
| 47 | * Branch 1 - 2 channels: channels 2 and 3 (FDB1 PCI dev 22.0) | ||
| 48 | * Each channel can have to 8 DIMM sets (called as SLOTS) | ||
| 49 | * Slots should generally be filled in pairs | ||
| 50 | * Except on Single Channel mode of operation | ||
| 51 | * just slot 0/channel0 filled on this mode | ||
| 52 | * On normal operation mode, the two channels on a branch should be | ||
| 53 | filled together for the same SLOT# | ||
| 54 | * When in mirrored mode, Branch 1 replicate memory at Branch 0, so, the four | ||
| 55 | * channels on both branches should be filled | ||
| 56 | */ | ||
| 57 | |||
| 58 | /* Limits for i7300 */ | ||
| 59 | #define MAX_SLOTS 8 | ||
| 60 | #define MAX_BRANCHES 2 | ||
| 61 | #define MAX_CH_PER_BRANCH 2 | ||
| 62 | #define MAX_CHANNELS (MAX_CH_PER_BRANCH * MAX_BRANCHES) | ||
| 63 | #define MAX_MIR 3 | ||
| 64 | |||
| 65 | #define to_channel(ch, branch) ((((branch)) << 1) | (ch)) | ||
| 66 | |||
| 67 | #define to_csrow(slot, ch, branch) \ | ||
| 68 | (to_channel(ch, branch) | ((slot) << 2)) | ||
| 69 | |||
| 70 | |||
| 71 | /* Device 16, | ||
| 72 | * Function 0: System Address (not documented) | ||
| 73 | * Function 1: Memory Branch Map, Control, Errors Register | ||
| 74 | * Function 2: FSB Error Registers | ||
| 75 | * | ||
| 76 | * All 3 functions of Device 16 (0,1,2) share the SAME DID and | ||
| 77 | * uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2), | ||
| 78 | * PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 | ||
| 79 | * for device 21 (0,1). | ||
| 80 | */ | ||
| 81 | |||
| 82 | /* OFFSETS for Function 0 */ | ||
| 83 | #define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */ | ||
| 84 | #define MAXCH 0x56 /* Max Channel Number */ | ||
| 85 | #define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */ | ||
| 86 | |||
| 87 | /* OFFSETS for Function 1 */ | ||
| 88 | #define TOLM 0x6C | ||
| 89 | #define REDMEMB 0x7C | ||
| 90 | |||
| 91 | #define MIR0 0x80 | ||
| 92 | #define MIR1 0x84 | ||
| 93 | #define MIR2 0x88 | ||
| 94 | |||
| 95 | #if 0 | ||
| 96 | #define AMIR0 0x8c | ||
| 97 | #define AMIR1 0x90 | ||
| 98 | #define AMIR2 0x94 | ||
| 99 | |||
| 100 | /*TODO: double check it */ | ||
| 101 | #define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3fe00) /* bits [17:9] indicate ODD, [8:0] indicate EVEN */ | ||
| 102 | |||
| 103 | /* Fatal error registers */ | ||
| 104 | #define FERR_FAT_FBD 0x98 | ||
| 105 | |||
| 106 | /*TODO: double check it */ | ||
| 107 | #define FERR_FAT_FBDCHAN (3<<28) /* channel index where the highest-order error occurred */ | ||
| 108 | |||
| 109 | #define NERR_FAT_FBD 0x9c | ||
| 110 | #define FERR_NF_FBD 0xa0 | ||
| 111 | |||
| 112 | /* Non-fatal error register */ | ||
| 113 | #define NERR_NF_FBD 0xa4 | ||
| 114 | |||
| 115 | /* Enable error mask */ | ||
| 116 | #define EMASK_FBD 0xa8 | ||
| 117 | |||
| 118 | #define ERR0_FBD 0xac | ||
| 119 | #define ERR1_FBD 0xb0 | ||
| 120 | #define ERR2_FBD 0xb4 | ||
| 121 | #define MCERR_FBD 0xb8 | ||
| 122 | |||
| 123 | #endif | ||
| 124 | |||
| 125 | /* TODO: Dev 16 fn1 allows memory error injection - offsets 0x100-0x10b */ | ||
| 126 | |||
| 127 | /* TODO: OFFSETS for Device 16 Function 2 */ | ||
| 128 | |||
| 129 | /* | ||
| 130 | * Device 21, | ||
| 131 | * Function 0: Memory Map Branch 0 | ||
| 132 | * | ||
| 133 | * Device 22, | ||
| 134 | * Function 0: Memory Map Branch 1 | ||
| 135 | */ | ||
| 136 | |||
| 137 | /* OFFSETS for Function 0 */ | ||
| 138 | |||
| 139 | /* | ||
| 140 | * Note: Other Intel EDAC drivers use AMBPRESENT to identify if the available | ||
| 141 | * memory. From datasheet item 7.3.1 (FB-DIMM technology & organization), it | ||
| 142 | * seems that we cannot use this information directly for the same usage. | ||
| 143 | * Each memory slot may have up to 2 AMB interfaces, one for income and another | ||
| 144 | * for outcome interface to the next slot. | ||
| 145 | * For now, the driver just stores the AMB present registers, but rely only at | ||
| 146 | * the MTR info to detect memory. | ||
| 147 | * Datasheet is also not clear about how to map each AMBPRESENT registers to | ||
| 148 | * one of the 4 available channels. | ||
| 149 | */ | ||
| 150 | #define AMBPRESENT_0 0x64 | ||
| 151 | #define AMBPRESENT_1 0x66 | ||
| 152 | |||
| 153 | const static u16 mtr_regs [MAX_SLOTS] = { | ||
| 154 | 0x80, 0x84, 0x88, 0x8c, | ||
| 155 | 0x82, 0x86, 0x8a, 0x8e | ||
| 156 | }; | ||
| 157 | |||
| 158 | /* Defines to extract the vaious fields from the | ||
| 159 | * MTRx - Memory Technology Registers | ||
| 160 | */ | ||
| 161 | #define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 8)) | ||
| 162 | #define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 7)) | ||
| 163 | #define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 6)) ? 8 : 4) | ||
| 164 | #define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 5)) ? 8 : 4) | ||
| 165 | #define MTR_DIMM_RANKS(mtr) (((mtr) & (1 << 4)) ? 1 : 0) | ||
| 166 | #define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3) | ||
| 167 | #define MTR_DRAM_BANKS_ADDR_BITS 2 | ||
| 168 | #define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13) | ||
| 169 | #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) | ||
| 170 | #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) | ||
| 171 | |||
| 172 | #if 0 | ||
| 173 | /* OFFSETS for Function 1 */ | ||
| 174 | |||
| 175 | /* TODO */ | ||
| 176 | #define NRECFGLOG 0x74 | ||
| 177 | #define RECFGLOG 0x78 | ||
| 178 | #define NRECMEMA 0xbe | ||
| 179 | #define NRECMEMB 0xc0 | ||
