^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Intel 82975X Memory Controller kernel module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) 2007 aCarLab (India) Pvt. Ltd. (http://acarlab.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (C) 2007 jetzbroadband (http://jetzbroadband.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file may be distributed under the terms of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * GNU General Public License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Written by Arvind R.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copied from i82875p_edac.c source:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/edac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define EDAC_MOD_STR "i82975x_edac"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define i82975x_printk(level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) edac_printk(level, "i82975x", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define i82975x_mc_printk(mci, level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) edac_mc_chipset_printk(mci, level, "i82975x", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #ifndef PCI_DEVICE_ID_INTEL_82975_0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PCI_DEVICE_ID_INTEL_82975_0 0x277c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #endif /* PCI_DEVICE_ID_INTEL_82975_0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define I82975X_NR_DIMMS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define I82975X_NR_CSROWS(nr_chans) (I82975X_NR_DIMMS / (nr_chans))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define I82975X_EAP 0x58 /* Dram Error Address Pointer (32b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * 31:7 128 byte cache-line address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * 6:1 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * 0 0: CH0; 1: CH1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define I82975X_DERRSYN 0x5c /* Dram Error SYNdrome (8b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * 7:0 DRAM ECC Syndrome
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define I82975X_DES 0x5d /* Dram ERRor DeSTination (8b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * 0h: Processor Memory Reads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * 1h:7h reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * More - See Page 65 of Intel DocSheet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define I82975X_ERRSTS 0xc8 /* Error Status Register (16b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * 15:12 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * 11 Thermal Sensor Event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * 10 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * 9 non-DRAM lock error (ndlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * 8 Refresh Timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * 7:2 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * 1 ECC UE (multibit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * 0 ECC CE (singlebit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Error Reporting is supported by 3 mechanisms:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 1. DMI SERR generation ( ERRCMD )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 2. SMI DMI generation ( SMICMD )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 3. SCI DMI generation ( SCICMD )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) NOTE: Only ONE of the three must be enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define I82975X_ERRCMD 0xca /* Error Command (16b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * 15:12 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * 11 Thermal Sensor Event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * 10 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * 9 non-DRAM lock error (ndlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * 8 Refresh Timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * 7:2 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * 1 ECC UE (multibit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * 0 ECC CE (singlebit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define I82975X_SMICMD 0xcc /* Error Command (16b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * 15:2 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * 1 ECC UE (multibit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * 0 ECC CE (singlebit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define I82975X_SCICMD 0xce /* Error Command (16b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * 15:2 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * 1 ECC UE (multibit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * 0 ECC CE (singlebit DRAM error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define I82975X_XEAP 0xfc /* Extended Dram Error Address Pointer (8b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * 7:1 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * 0 Bit32 of the Dram Error Address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define I82975X_MCHBAR 0x44 /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * 31:14 Base Addr of 16K memory-mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * configuration space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * 13:1 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * 0 mem-mapped config space enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Intel 82975x memory mapped register space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define I82975X_DRB_SHIFT 25 /* fixed 32MiB grain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define I82975X_DRB 0x100 /* DRAM Row Boundary (8b x 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * 7 set to 1 in highest DRB of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * channel if 4GB in ch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * 6:2 upper boundary of rank in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * 32MB grains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * 1:0 set to 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define I82975X_DRB_CH0R0 0x100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define I82975X_DRB_CH0R1 0x101
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define I82975X_DRB_CH0R2 0x102
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define I82975X_DRB_CH0R3 0x103
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define I82975X_DRB_CH1R0 0x180
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define I82975X_DRB_CH1R1 0x181
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define I82975X_DRB_CH1R2 0x182
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define I82975X_DRB_CH1R3 0x183
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define I82975X_DRA 0x108 /* DRAM Row Attribute (4b x 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * defines the PAGE SIZE to be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * for the rank
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * 7 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * 6:4 row attr of odd rank, i.e. 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * 3 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * 2:0 row attr of even rank, i.e. 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * 000 = unpopulated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * 001 = reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * 010 = 4KiB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * 011 = 8KiB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * 100 = 16KiB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * others = reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define I82975X_DRA_CH0R01 0x108
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define I82975X_DRA_CH0R23 0x109
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define I82975X_DRA_CH1R01 0x188
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define I82975X_DRA_CH1R23 0x189
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define I82975X_BNKARC 0x10e /* Type of device in each rank - Bank Arch (16b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * 15:8 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * 7:6 Rank 3 architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * 5:4 Rank 2 architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * 3:2 Rank 1 architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * 1:0 Rank 0 architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * 00 => 4 banks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * 01 => 8 banks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define I82975X_C0BNKARC 0x10e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define I82975X_C1BNKARC 0x18e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define I82975X_DRC 0x120 /* DRAM Controller Mode0 (32b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * 31:30 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * 29 init complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * 28:11 reserved, according to Intel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * 22:21 number of channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * 00=1 01=2 in 82875
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * seems to be ECC mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * bits in 82975 in Asus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * P5W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * 19:18 Data Integ Mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * 00=none 01=ECC in 82875
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * 10:8 refresh mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * 7 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * 6:4 mode select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * 3:2 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * 1:0 DRAM type 10=Second Revision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * DDR2 SDRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * 00, 01, 11 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define I82975X_DRC_CH0M0 0x120
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define I82975X_DRC_CH1M0 0x1A0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define I82975X_DRC_M1 0x124 /* DRAM Controller Mode1 (32b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * 31 0=Standard Address Map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * 1=Enhanced Address Map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * 30:0 reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define I82975X_DRC_CH0M1 0x124
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define I82975X_DRC_CH1M1 0x1A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) enum i82975x_chips {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) I82975X = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct i82975x_pvt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) void __iomem *mch_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct i82975x_dev_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) const char *ctl_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct i82975x_error_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u16 errsts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u32 eap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) u8 des;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u8 derrsyn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u16 errsts2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u8 chan; /* the channel is bit 0 of EAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u8 xeap; /* extended eap bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static const struct i82975x_dev_info i82975x_devs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) [I82975X] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .ctl_name = "i82975x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * already registered driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int i82975x_registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static void i82975x_get_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct i82975x_error_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) pdev = to_pci_dev(mci->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * This is a mess because there is no atomic way to read all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * registers at once and the registers can transition from CE being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * overwritten by UE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) pci_read_config_word(pdev, I82975X_ERRSTS, &info->errsts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) pci_read_config_dword(pdev, I82975X_EAP, &info->eap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) pci_read_config_byte(pdev, I82975X_XEAP, &info->xeap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) pci_read_config_byte(pdev, I82975X_DES, &info->des);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) pci_read_config_byte(pdev, I82975X_DERRSYN, &info->derrsyn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) pci_read_config_word(pdev, I82975X_ERRSTS, &info->errsts2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) pci_write_bits16(pdev, I82975X_ERRSTS, 0x0003, 0x0003);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * If the error is the same then we can for both reads then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * the first set of reads is valid. If there is a change then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * there is a CE no info and the second set of reads is valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * and should be UE info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!(info->errsts2 & 0x0003))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if ((info->errsts ^ info->errsts2) & 0x0003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) pci_read_config_dword(pdev, I82975X_EAP, &info->eap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) pci_read_config_byte(pdev, I82975X_XEAP, &info->xeap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) pci_read_config_byte(pdev, I82975X_DES, &info->des);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pci_read_config_byte(pdev, I82975X_DERRSYN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) &info->derrsyn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int i82975x_process_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct i82975x_error_info *info, int handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int row, chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) unsigned long offst, page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (!(info->errsts2 & 0x0003))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if ((info->errsts ^ info->errsts2) & 0x0003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) -1, -1, -1, "UE overwrote CE", "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) info->errsts = info->errsts2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) page = (unsigned long) info->eap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) page >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (info->xeap & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) page |= 0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) page >>= (PAGE_SHIFT - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) row = edac_mc_find_csrow_by_page(mci, page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (row == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) i82975x_mc_printk(mci, KERN_ERR, "error processing EAP:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) "\tXEAP=%u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) "\t EAP=0x%08x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) "\tPAGE=0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) offst = info->eap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) & ((1 << PAGE_SHIFT) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) (1 << mci->csrows[row]->channels[chan]->dimm->grain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (info->errsts & 0x0002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) page, offst, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) row, -1, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) "i82975x UE", "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) page, offst, info->derrsyn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) row, chan ? chan : 0, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) "i82975x CE", "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static void i82975x_check(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct i82975x_error_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) edac_dbg(1, "MC%d\n", mci->mc_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) i82975x_get_error_info(mci, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) i82975x_process_error_info(mci, &info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Return 1 if dual channel mode is active. Else return 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int dual_channel_active(void __iomem *mch_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * We treat interleaved-symmetric configuration as dual-channel - EAP's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * bit-0 giving the channel of the error location.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * All other configurations are treated as single channel - the EAP's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * bit-0 will resolve ok in symmetric area of mixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * (symmetric/asymmetric) configurations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u8 drb[4][2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int dualch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) for (dualch = 1, row = 0; dualch && (row < 4); row++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) drb[row][0] = readb(mch_window + I82975X_DRB + row);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) drb[row][1] = readb(mch_window + I82975X_DRB + row + 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dualch = dualch && (drb[row][0] == drb[row][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return dualch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static void i82975x_init_csrows(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct pci_dev *pdev, void __iomem *mch_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct csrow_info *csrow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) unsigned long last_cumul_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) u32 cumul_size, nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int index, chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct dimm_info *dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) last_cumul_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * 82875 comment:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * The dram row boundary (DRB) reg values are boundary address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * for each DRAM row with a granularity of 32 or 64MB (single/dual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * channel operation). DRB regs are cumulative; therefore DRB7 will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * contain the total memory contained in all rows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) for (index = 0; index < mci->nr_csrows; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) csrow = mci->csrows[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) value = readb(mch_window + I82975X_DRB + index +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ((index >= 4) ? 0x80 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) cumul_size = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * Adjust cumul_size w.r.t number of channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (csrow->nr_channels > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) cumul_size <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) nr_pages = cumul_size - last_cumul_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (!nr_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * Initialise dram labels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * index values:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * [0-7] for single-channel; i.e. csrow->nr_channels = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * [0-3] for dual-channel; i.e. csrow->nr_channels = 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) for (chan = 0; chan < csrow->nr_channels; chan++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) dimm = mci->csrows[index]->channels[chan]->dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) dimm->nr_pages = nr_pages / csrow->nr_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) (chan == 0) ? 'A' : 'B',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) dimm->grain = 1 << 7; /* 128Byte cache-line resolution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* ECC is possible on i92975x ONLY with DEV_X8. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dimm->dtype = DEV_X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) dimm->edac_mode = EDAC_SECDED; /* only supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) csrow->first_page = last_cumul_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) csrow->last_page = cumul_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) last_cumul_size = cumul_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* #define i82975x_DEBUG_IOMEM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) #ifdef i82975x_DEBUG_IOMEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static void i82975x_print_dram_timings(void __iomem *mch_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * The register meanings are from Intel specs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * (shows 13-5-5-5 for 800-DDR2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * Asus P5W Bios reports 15-5-4-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * What's your religion?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static const int caslats[4] = { 5, 4, 3, 6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) u32 dtreg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) dtreg[0] = readl(mch_window + 0x114);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dtreg[1] = readl(mch_window + 0x194);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) i82975x_printk(KERN_INFO, "DRAM Timings : Ch0 Ch1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) " RAS Active Min = %d %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) " CAS latency = %d %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) " RAS to CAS = %d %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) " RAS precharge = %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) (dtreg[0] >> 19 ) & 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) (dtreg[1] >> 19) & 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) caslats[(dtreg[0] >> 8) & 0x03],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) caslats[(dtreg[1] >> 8) & 0x03],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ((dtreg[0] >> 4) & 0x07) + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ((dtreg[1] >> 4) & 0x07) + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) (dtreg[0] & 0x07) + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) (dtreg[1] & 0x07) + 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int i82975x_probe1(struct pci_dev *pdev, int dev_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) int rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct edac_mc_layer layers[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct i82975x_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) void __iomem *mch_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) u32 mchbar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) u32 drc[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct i82975x_error_info discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) #ifdef i82975x_DEBUG_IOMEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) u8 c0drb[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) u8 c1drb[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) pci_read_config_dword(pdev, I82975X_MCHBAR, &mchbar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (!(mchbar & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) edac_dbg(3, "failed, MCHBAR disabled!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) mch_window = ioremap(mchbar, 0x1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (!mch_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) edac_dbg(3, "error ioremapping MCHBAR!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) #ifdef i82975x_DEBUG_IOMEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) mchbar, mch_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) drc[0] = readl(mch_window + I82975X_DRC_CH0M0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) drc[1] = readl(mch_window + I82975X_DRC_CH1M0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) #ifdef i82975x_DEBUG_IOMEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ((drc[0] >> 21) & 3) == 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) "ECC enabled" : "ECC disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ((drc[1] >> 21) & 3) == 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) "ECC enabled" : "ECC disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) readw(mch_window + I82975X_C0BNKARC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) readw(mch_window + I82975X_C1BNKARC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) i82975x_print_dram_timings(mch_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) chans = dual_channel_active(mch_window) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* assuming only one controller, index thus is 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) layers[0].size = I82975X_NR_DIMMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) layers[0].is_virt_csrow = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) layers[1].type = EDAC_MC_LAYER_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) layers[1].size = I82975X_NR_CSROWS(chans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) layers[1].is_virt_csrow = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (!mci) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) edac_dbg(3, "init mci\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) mci->pdev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) mci->mtype_cap = MEM_FLAG_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mci->mod_name = EDAC_MOD_STR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) mci->ctl_name = i82975x_devs[dev_idx].ctl_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) mci->dev_name = pci_name(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) mci->edac_check = i82975x_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) mci->ctl_page_to_phys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) edac_dbg(3, "init pvt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) pvt = (struct i82975x_pvt *) mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) pvt->mch_window = mch_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) i82975x_init_csrows(mci, pdev, mch_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) mci->scrub_mode = SCRUB_HW_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) i82975x_get_error_info(mci, &discard); /* clear counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* finalize this instance of memory controller with edac core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (edac_mc_add_mc(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) edac_dbg(3, "failed edac_mc_add_mc()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto fail2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* get this far and it's successful */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) edac_dbg(3, "success\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) fail2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) iounmap(mch_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) fail0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* returns count (>= 0), or negative on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static int i82975x_init_one(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (pci_enable_device(pdev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) rc = i82975x_probe1(pdev, ent->driver_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (mci_pdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) mci_pdev = pci_dev_get(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static void i82975x_remove_one(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct i82975x_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) mci = edac_mc_del_mc(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (mci == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (pvt->mch_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) iounmap( pvt->mch_window );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static const struct pci_device_id i82975x_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) PCI_VEND_DEV(INTEL, 82975_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) I82975X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) } /* 0 terminated list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) MODULE_DEVICE_TABLE(pci, i82975x_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static struct pci_driver i82975x_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) .name = EDAC_MOD_STR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .probe = i82975x_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) .remove = i82975x_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) .id_table = i82975x_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static int __init i82975x_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int pci_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) edac_dbg(3, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* Ensure that the OPSTATE is set correctly for POLL or NMI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) opstate_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) pci_rc = pci_register_driver(&i82975x_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (pci_rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (mci_pdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) PCI_DEVICE_ID_INTEL_82975_0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!mci_pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) edac_dbg(0, "i82975x pci_get_device fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) pci_rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) pci_rc = i82975x_init_one(mci_pdev, i82975x_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (pci_rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) edac_dbg(0, "i82975x init fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) pci_rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) pci_unregister_driver(&i82975x_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) fail0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) pci_dev_put(mci_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return pci_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static void __exit i82975x_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) edac_dbg(3, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) pci_unregister_driver(&i82975x_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!i82975x_registered) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) i82975x_remove_one(mci_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) pci_dev_put(mci_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) module_init(i82975x_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) module_exit(i82975x_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) MODULE_AUTHOR("Arvind R. <arvino55@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) MODULE_DESCRIPTION("MC support for Intel 82975 memory hub controllers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) module_param(edac_op_state, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");