1806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox/* 2806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * Intel e752x Memory Controller kernel module 3806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * (C) 2004 Linux Networx (http://lnxi.com) 4806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * This file may be distributed under the terms of the 5806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * GNU General Public License. 6806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 7806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * See "enum e752x_chips" below for supported chipsets 8806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 9806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * Written by Tom Zimmerman 10806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 11806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * Contributors: 12806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * Thayne Harbaugh at realmsys.com (?) 13806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * Wang Zhenyu at intel.com 14806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * Dave Jiang at mvista.com 15806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 16da9bb1d27b21cb24cbb6a2efb5d3c464d357a01eAlan Cox * $Id: edac_e752x.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $ 17806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 18806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 19806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 20806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#include <linux/module.h> 21806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#include <linux/init.h> 22806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#include <linux/pci.h> 23806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#include <linux/pci_ids.h> 24c0d121720220584bba2876b032e58a076b843fa1Dave Jiang#include <linux/edac.h> 2520bcb7a81dee21bfa3408f03f46b2891c9b5c84bDouglas Thompson#include "edac_core.h" 26806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 27152ba3942276c2a240703669ae4a3099e0a79451Michal Marek#define E752X_REVISION " Ver: 2.0.2" 28929a40ec324e947d4ad14cc1ced785c104c560e2Doug Thompson#define EDAC_MOD_STR "e752x_edac" 2937f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson 3010d33e9c36827e5371479e55ef4089e000af2638Doug Thompsonstatic int report_non_memory_errors; 3196941026a51e9cb8c2d2be7499301b7fcd9ee225mark grossstatic int force_function_unhide; 3294ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyserstatic int sysbus_parity = -1; 3396941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross 3491b99041c1d577ded1da599ddc28cec2e07253cfDave Jiangstatic struct edac_pci_ctl_info *e752x_pci; 3591b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang 36537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson#define e752x_printk(level, fmt, arg...) \ 37e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson edac_printk(level, "e752x", fmt, ##arg) 38537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson 39537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson#define e752x_mc_printk(mci, level, fmt, arg...) \ 40e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg) 41537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson 42806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#ifndef PCI_DEVICE_ID_INTEL_7520_0 43806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define PCI_DEVICE_ID_INTEL_7520_0 0x3590 44806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#endif /* PCI_DEVICE_ID_INTEL_7520_0 */ 45806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 46806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#ifndef PCI_DEVICE_ID_INTEL_7520_1_ERR 47806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define PCI_DEVICE_ID_INTEL_7520_1_ERR 0x3591 48806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#endif /* PCI_DEVICE_ID_INTEL_7520_1_ERR */ 49806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 50806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#ifndef PCI_DEVICE_ID_INTEL_7525_0 51806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define PCI_DEVICE_ID_INTEL_7525_0 0x359E 52806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#endif /* PCI_DEVICE_ID_INTEL_7525_0 */ 53806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 54806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#ifndef PCI_DEVICE_ID_INTEL_7525_1_ERR 55806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define PCI_DEVICE_ID_INTEL_7525_1_ERR 0x3593 56806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#endif /* PCI_DEVICE_ID_INTEL_7525_1_ERR */ 57806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 58806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#ifndef PCI_DEVICE_ID_INTEL_7320_0 59806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define PCI_DEVICE_ID_INTEL_7320_0 0x3592 60806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#endif /* PCI_DEVICE_ID_INTEL_7320_0 */ 61806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 62806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#ifndef PCI_DEVICE_ID_INTEL_7320_1_ERR 63806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593 64806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */ 65806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 665135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#ifndef PCI_DEVICE_ID_INTEL_3100_0 675135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define PCI_DEVICE_ID_INTEL_3100_0 0x35B0 685135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#endif /* PCI_DEVICE_ID_INTEL_3100_0 */ 695135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 705135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#ifndef PCI_DEVICE_ID_INTEL_3100_1_ERR 715135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define PCI_DEVICE_ID_INTEL_3100_1_ERR 0x35B1 725135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#endif /* PCI_DEVICE_ID_INTEL_3100_1_ERR */ 735135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 74806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_NR_CSROWS 8 /* number of csrows */ 75806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 76806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox/* E752X register addresses - device 0 function 0 */ 778004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser#define E752X_MCHSCRB 0x52 /* Memory Scrub register (16b) */ 788004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser /* 798004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * 6:5 Scrub Completion Count 808004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * 3:2 Scrub Rate (i3100 only) 818004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * 01=fast 10=normal 828004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * 1:0 Scrub Mode enable 838004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * 00=off 10=on 848004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser */ 85806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRB 0x60 /* DRAM row boundary register (8b) */ 86806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRA 0x70 /* DRAM row attribute register (8b) */ 87806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 88806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 31:30 Device width row 7 89806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 01=x8 10=x4 11=x8 DDR2 90806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 27:26 Device width row 6 91806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 23:22 Device width row 5 92806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 19:20 Device width row 4 93806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 15:14 Device width row 3 94806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 11:10 Device width row 2 95806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 7:6 Device width row 1 96806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 3:2 Device width row 0 97806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 98806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRC 0x7C /* DRAM controller mode reg (32b) */ 99806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* FIXME:IS THIS RIGHT? */ 100806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 101806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 22 Number channels 0=1,1=2 102806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 19:18 DRB Granularity 32/64MB 103806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 104806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRM 0x80 /* Dimm mapping register */ 105806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DDRCSR 0x9A /* DDR control and status reg (16b) */ 106806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 107806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 14:12 1 single A, 2 single B, 3 dual 108806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 109806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_TOLM 0xC4 /* DRAM top of low memory reg (16b) */ 110806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */ 111806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */ 112806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_REMAPOFFSET 0xCA /* DRAM remap limit offset reg (16b) */ 113806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 114806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox/* E752X register addresses - device 0 function 1 */ 115806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_FERR_GLOBAL 0x40 /* Global first error register (32b) */ 116806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_NERR_GLOBAL 0x44 /* Global next error register (32b) */ 117806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_HI_FERR 0x50 /* Hub interface first error reg (8b) */ 118806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_HI_NERR 0x52 /* Hub interface next error reg (8b) */ 119806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_HI_ERRMASK 0x54 /* Hub interface error mask reg (8b) */ 120806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_HI_SMICMD 0x5A /* Hub interface SMI command reg (8b) */ 121806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_SYSBUS_FERR 0x60 /* System buss first error reg (16b) */ 122806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_SYSBUS_NERR 0x62 /* System buss next error reg (16b) */ 123806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_SYSBUS_ERRMASK 0x64 /* System buss error mask reg (16b) */ 124806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_SYSBUS_SMICMD 0x6A /* System buss SMI command reg (16b) */ 125806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */ 126806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */ 127806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */ 12810d33e9c36827e5371479e55ef4089e000af2638Doug Thompson#define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI cmd reg (8b) */ 129806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */ 130806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */ 131806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */ 132806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_SMICMD 0x8A /* DRAM SMI command register (8b) */ 133806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_RETR_ADD 0xAC /* DRAM Retry address register (32b) */ 134806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_SEC1_ADD 0xA0 /* DRAM first correctable memory */ 135806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* error address register (32b) */ 136806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 137806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 31 Reserved 13810d33e9c36827e5371479e55ef4089e000af2638Doug Thompson * 30:2 CE address (64 byte block 34:6 139806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 1 Reserved 140806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 0 HiLoCS 141806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 142806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_SEC2_ADD 0xC8 /* DRAM first correctable memory */ 143806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* error address register (32b) */ 144806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 145806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 31 Reserved 146806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 30:2 CE address (64 byte block 34:6) 147806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 1 Reserved 148806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 0 HiLoCS 149806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 150806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_DED_ADD 0xA4 /* DRAM first uncorrectable memory */ 151806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* error address register (32b) */ 152806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 153806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 31 Reserved 154806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 30:2 CE address (64 byte block 34:6) 155806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 1 Reserved 156806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 0 HiLoCS 157806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 15810d33e9c36827e5371479e55ef4089e000af2638Doug Thompson#define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM 1st uncorrectable scrub mem */ 159806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* error address register (32b) */ 160806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 161806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 31 Reserved 16210d33e9c36827e5371479e55ef4089e000af2638Doug Thompson * 30:2 CE address (64 byte block 34:6 163806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 1 Reserved 164806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox * 0 HiLoCS 165806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox */ 166806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_SEC1_SYNDROME 0xC4 /* DRAM first correctable memory */ 167806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* error syndrome register (16b) */ 168806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DRAM_SEC2_SYNDROME 0xC6 /* DRAM second correctable memory */ 169806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* error syndrome register (16b) */ 170806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */ 171806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1725135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov/* 3100 IMCH specific register addresses - device 0 function 1 */ 1735135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define I3100_NSI_FERR 0x48 /* NSI first error reg (32b) */ 1745135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define I3100_NSI_NERR 0x4C /* NSI next error reg (32b) */ 1755135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define I3100_NSI_SMICMD 0x54 /* NSI SMI command register (32b) */ 1765135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define I3100_NSI_EMASK 0x90 /* NSI error mask register (32b) */ 1775135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 178806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox/* ICH5R register addresses - device 30 function 0 */ 179806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */ 180806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */ 181806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox#define ICH5R_PCI_BRIDGE_CTL 0x3E /* PCI bridge control register (16b) */ 182806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 183806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxenum e752x_chips { 184806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox E7520 = 0, 185806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox E7525 = 1, 1865135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov E7320 = 2, 1875135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov I3100 = 3 188806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 189806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 190806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstruct e752x_pvt { 191806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct pci_dev *bridge_ck; 192806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct pci_dev *dev_d0f0; 193806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct pci_dev *dev_d0f1; 194806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 tolm; 195806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 remapbase; 196806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 remaplimit; 197806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int mc_symmetric; 198806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u8 map[8]; 199806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int map_type; 200806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox const struct e752x_dev_info *dev_info; 201806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 202806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 203806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstruct e752x_dev_info { 204806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 err_dev; 2053847bccce80c8a01d7adbad9961564252207302aDave Peterson u16 ctl_dev; 206806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox const char *ctl_name; 207806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 208806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 209806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstruct e752x_error_info { 210806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 ferr_global; 211806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 nerr_global; 2125135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov u32 nsi_ferr; /* 3100 only */ 2135135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov u32 nsi_nerr; /* 3100 only */ 2145135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov u8 hi_ferr; /* all but 3100 */ 2155135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov u8 hi_nerr; /* all but 3100 */ 216806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 sysbus_ferr; 217806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 sysbus_nerr; 218806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u8 buf_ferr; 219806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u8 buf_nerr; 220806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 dram_ferr; 221806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 dram_nerr; 222806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 dram_sec1_add; 223806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 dram_sec2_add; 224806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 dram_sec1_syndrome; 225806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 dram_sec2_syndrome; 226806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 dram_ded_add; 227806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 dram_scrb_add; 228806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 dram_retr_add; 229806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 230806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 231806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic const struct e752x_dev_info e752x_devs[] = { 232806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox [E7520] = { 233052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR, 234052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .ctl_dev = PCI_DEVICE_ID_INTEL_7520_0, 235052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .ctl_name = "E7520"}, 236806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox [E7525] = { 237052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR, 238052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .ctl_dev = PCI_DEVICE_ID_INTEL_7525_0, 239052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .ctl_name = "E7525"}, 240806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox [E7320] = { 241052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, 242052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0, 243052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .ctl_name = "E7320"}, 2445135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov [I3100] = { 2455135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov .err_dev = PCI_DEVICE_ID_INTEL_3100_1_ERR, 2465135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov .ctl_dev = PCI_DEVICE_ID_INTEL_3100_0, 2475135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov .ctl_name = "3100"}, 248806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 249806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 2508004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser/* Valid scrub rates for the e752x/3100 hardware memory scrubber. We 2518004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * map the scrubbing bandwidth to a hardware register value. The 'set' 2528004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * operation finds the 'matching or higher value'. Note that scrubbing 2538004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * on the e752x can only be enabled/disabled. The 3100 supports 2548004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * a normal and fast mode. 2558004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser */ 2568004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 2578004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser#define SDRATE_EOT 0xFFFFFFFF 2588004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 2598004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyserstruct scrubrate { 2608004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser u32 bandwidth; /* bandwidth consumed by scrubbing in bytes/sec */ 2618004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser u16 scrubval; /* register value for scrub rate */ 2628004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser}; 2638004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 2648004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser/* Rate below assumes same performance as i3100 using PC3200 DDR2 in 2658004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * normal mode. e752x bridges don't support choosing normal or fast mode, 2668004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * so the scrubbing bandwidth value isn't all that important - scrubbing is 2678004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * either on or off. 2688004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser */ 2698004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyserstatic const struct scrubrate scrubrates_e752x[] = { 2708004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser {0, 0x00}, /* Scrubbing Off */ 2718004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser {500000, 0x02}, /* Scrubbing On */ 2728004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser {SDRATE_EOT, 0x00} /* End of Table */ 2738004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser}; 2748004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 2758004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser/* Fast mode: 2 GByte PC3200 DDR2 scrubbed in 33s = 63161283 bytes/s 2768004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * Normal mode: 125 (32000 / 256) times slower than fast mode. 2778004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser */ 2788004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyserstatic const struct scrubrate scrubrates_i3100[] = { 2798004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser {0, 0x00}, /* Scrubbing Off */ 2808004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser {500000, 0x0a}, /* Normal mode - 32k clocks */ 2818004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser {62500000, 0x06}, /* Fast mode - 256 clocks */ 2828004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser {SDRATE_EOT, 0x00} /* End of Table */ 2838004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser}; 2848004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 285806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, 286052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson unsigned long page) 287806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 288806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 remap; 289203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; 290806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 291537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 292806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 293806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (page < pvt->tolm) 294806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return page; 295e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 296806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if ((page >= 0x100000) && (page < pvt->remapbase)) 297806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return page; 298e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 299806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox remap = (page - pvt->tolm) + pvt->remapbase; 300e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 301806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (remap < pvt->remaplimit) 302806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return remap; 303e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 304537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_printk(KERN_ERR, "Invalid page %lx - out of range\n", page); 305806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return pvt->tolm - 1; 306806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 307806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 308806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void do_process_ce(struct mem_ctl_info *mci, u16 error_one, 309052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson u32 sec1_add, u16 sec1_syndrome) 310806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 311806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 page; 312806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int row; 313806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int channel; 314806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int i; 315203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; 316806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 317537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 318806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 319806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* convert the addr to 4k page */ 320806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox page = sec1_add >> (PAGE_SHIFT - 4); 321806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 322806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* FIXME - check for -1 */ 323806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (pvt->mc_symmetric) { 324806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* chip select are bits 14 & 13 */ 325806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox row = ((page >> 1) & 3); 326537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_printk(KERN_WARNING, 327052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "Test row %d Table %d %d %d %d %d %d %d %d\n", row, 328052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson pvt->map[0], pvt->map[1], pvt->map[2], pvt->map[3], 329052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson pvt->map[4], pvt->map[5], pvt->map[6], 330052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson pvt->map[7]); 331806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 332806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* test for channel remapping */ 333806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox for (i = 0; i < 8; i++) { 334806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (pvt->map[i] == row) 335806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox break; 336806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 337e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 338537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_printk(KERN_WARNING, "Test computed row %d\n", i); 339e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 340806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (i < 8) 341806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox row = i; 342806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox else 343537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_mc_printk(mci, KERN_WARNING, 344203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang "row %d not found in remap table\n", 345203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang row); 346806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } else 347806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox row = edac_mc_find_csrow_by_page(mci, page); 348e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 349806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* 0 = channel A, 1 = channel B */ 350806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox channel = !(error_one & 1); 351806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 35284db003f249ddbcde1666376b4e3bbe9ee2c7c0cMike Chan /* e752x mc reads 34:6 of the DRAM linear address */ 35384db003f249ddbcde1666376b4e3bbe9ee2c7c0cMike Chan edac_mc_handle_ce(mci, page, offset_in_page(sec1_add << 4), 354052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson sec1_syndrome, row, channel, "e752x CE"); 355806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 356806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 357806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void process_ce(struct mem_ctl_info *mci, u16 error_one, 358052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson u32 sec1_add, u16 sec1_syndrome, int *error_found, 359052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int handle_error) 360806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 361806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 362806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 363806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 364806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox do_process_ce(mci, error_one, sec1_add, sec1_syndrome); 365806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 366806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 367e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Petersonstatic void do_process_ue(struct mem_ctl_info *mci, u16 error_one, 368052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson u32 ded_add, u32 scrb_add) 369806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 370806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 error_2b, block_page; 371806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int row; 372203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; 373806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 374537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 375806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 376806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (error_one & 0x0202) { 377806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error_2b = ded_add; 378e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 379806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* convert to 4k address */ 380806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox block_page = error_2b >> (PAGE_SHIFT - 4); 381e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 382806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox row = pvt->mc_symmetric ? 383052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson /* chip select are bits 14 & 13 */ 384052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson ((block_page >> 1) & 3) : 385052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson edac_mc_find_csrow_by_page(mci, block_page); 386e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 38784db003f249ddbcde1666376b4e3bbe9ee2c7c0cMike Chan /* e752x mc reads 34:6 of the DRAM linear address */ 38884db003f249ddbcde1666376b4e3bbe9ee2c7c0cMike Chan edac_mc_handle_ue(mci, block_page, 389052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson offset_in_page(error_2b << 4), 390052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson row, "e752x UE from Read"); 391806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 392806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (error_one & 0x0404) { 393806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error_2b = scrb_add; 394e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 395806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* convert to 4k address */ 396806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox block_page = error_2b >> (PAGE_SHIFT - 4); 397e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 398806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox row = pvt->mc_symmetric ? 399052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson /* chip select are bits 14 & 13 */ 400052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson ((block_page >> 1) & 3) : 401052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson edac_mc_find_csrow_by_page(mci, block_page); 402e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 40384db003f249ddbcde1666376b4e3bbe9ee2c7c0cMike Chan /* e752x mc reads 34:6 of the DRAM linear address */ 40484db003f249ddbcde1666376b4e3bbe9ee2c7c0cMike Chan edac_mc_handle_ue(mci, block_page, 405052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson offset_in_page(error_2b << 4), 406052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson row, "e752x UE from Scruber"); 407806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 408806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 409806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 410806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void process_ue(struct mem_ctl_info *mci, u16 error_one, 411052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson u32 ded_add, u32 scrb_add, int *error_found, 412052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int handle_error) 413806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 414806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 415806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 416806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 417806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox do_process_ue(mci, error_one, ded_add, scrb_add); 418806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 419806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 420806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void process_ue_no_info_wr(struct mem_ctl_info *mci, 421203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang int *error_found, int handle_error) 422806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 423806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 424806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 425806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (!handle_error) 426806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return; 427806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 428537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 429806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox edac_mc_handle_ue_no_info(mci, "e752x UE log memory write"); 430806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 431806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 432806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, 433203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang u32 retry_add) 434806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 435806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 error_1b, page; 436806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int row; 437203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; 438806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 439806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error_1b = retry_add; 44010d33e9c36827e5371479e55ef4089e000af2638Doug Thompson page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ 44110d33e9c36827e5371479e55ef4089e000af2638Doug Thompson 44210d33e9c36827e5371479e55ef4089e000af2638Doug Thompson /* chip select are bits 14 & 13 */ 44310d33e9c36827e5371479e55ef4089e000af2638Doug Thompson row = pvt->mc_symmetric ? ((page >> 1) & 3) : 444052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson edac_mc_find_csrow_by_page(mci, page); 44510d33e9c36827e5371479e55ef4089e000af2638Doug Thompson 446537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_mc_printk(mci, KERN_WARNING, 447203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang "CE page 0x%lx, row %d : Memory read retry\n", 448203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang (long unsigned int)page, row); 449806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 450806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 451806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void process_ded_retry(struct mem_ctl_info *mci, u16 error, 452052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson u32 retry_add, int *error_found, 453052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int handle_error) 454806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 455806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 456806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 457806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 458806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox do_process_ded_retry(mci, error, retry_add); 459806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 460806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 461806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error, 462203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang int *error_found, int handle_error) 463806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 464806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 465806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 466806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 467537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_mc_printk(mci, KERN_WARNING, "Memory threshold CE\n"); 468806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 469806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 470da9bb1d27b21cb24cbb6a2efb5d3c464d357a01eAlan Coxstatic char *global_message[11] = { 47110d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "PCI Express C1", 47210d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "PCI Express C", 47310d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "PCI Express B1", 47410d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "PCI Express B", 47510d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "PCI Express A1", 47610d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "PCI Express A", 47710d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "DMA Controller", 47810d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "HUB or NS Interface", 47910d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "System Bus", 48010d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "DRAM Controller", /* 9th entry */ 48110d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "Internal Buffer" 482806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 483806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 48410d33e9c36827e5371479e55ef4089e000af2638Doug Thompson#define DRAM_ENTRY 9 48510d33e9c36827e5371479e55ef4089e000af2638Doug Thompson 486da9bb1d27b21cb24cbb6a2efb5d3c464d357a01eAlan Coxstatic char *fatal_message[2] = { "Non-Fatal ", "Fatal " }; 487806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 488806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void do_global_error(int fatal, u32 errors) 489806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 490806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int i; 491806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 492806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox for (i = 0; i < 11; i++) { 49310d33e9c36827e5371479e55ef4089e000af2638Doug Thompson if (errors & (1 << i)) { 49410d33e9c36827e5371479e55ef4089e000af2638Doug Thompson /* If the error is from DRAM Controller OR 49510d33e9c36827e5371479e55ef4089e000af2638Doug Thompson * we are to report ALL errors, then 49610d33e9c36827e5371479e55ef4089e000af2638Doug Thompson * report the error 49710d33e9c36827e5371479e55ef4089e000af2638Doug Thompson */ 49810d33e9c36827e5371479e55ef4089e000af2638Doug Thompson if ((i == DRAM_ENTRY) || report_non_memory_errors) 49910d33e9c36827e5371479e55ef4089e000af2638Doug Thompson e752x_printk(KERN_WARNING, "%sError %s\n", 50010d33e9c36827e5371479e55ef4089e000af2638Doug Thompson fatal_message[fatal], 50110d33e9c36827e5371479e55ef4089e000af2638Doug Thompson global_message[i]); 50210d33e9c36827e5371479e55ef4089e000af2638Doug Thompson } 503806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 504806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 505806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 506806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void global_error(int fatal, u32 errors, int *error_found, 507203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang int handle_error) 508806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 509806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 510806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 511806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 512806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox do_global_error(fatal, errors); 513806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 514806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 515da9bb1d27b21cb24cbb6a2efb5d3c464d357a01eAlan Coxstatic char *hub_message[7] = { 516806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "HI Address or Command Parity", "HI Illegal Access", 517806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "HI Internal Parity", "Out of Range Access", 518806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "HI Data Parity", "Enhanced Config Access", 519806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Hub Interface Target Abort" 520806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 521806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 522806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void do_hub_error(int fatal, u8 errors) 523806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 524806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int i; 525806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 526806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox for (i = 0; i < 7; i++) { 527806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (errors & (1 << i)) 528537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_printk(KERN_WARNING, "%sError %s\n", 529052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson fatal_message[fatal], hub_message[i]); 530806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 531806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 532806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 533806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void hub_error(int fatal, u8 errors, int *error_found, 534052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int handle_error) 535806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 536806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 537806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 538806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 539806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox do_hub_error(fatal, errors); 540806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 541806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 5425135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define NSI_FATAL_MASK 0x0c080081 5435135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define NSI_NON_FATAL_MASK 0x23a0ba64 5445135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov#define NSI_ERR_MASK (NSI_FATAL_MASK | NSI_NON_FATAL_MASK) 5455135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 5465135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalovstatic char *nsi_message[30] = { 5475135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "NSI Link Down", /* NSI_FERR/NSI_NERR bit 0, fatal error */ 5485135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5495135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "NSI Parity Error", /* bit 2, non-fatal */ 5505135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5515135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5525135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Correctable Error Message", /* bit 5, non-fatal */ 5535135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Non-Fatal Error Message", /* bit 6, non-fatal */ 5545135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Fatal Error Message", /* bit 7, fatal */ 5555135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5565135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Receiver Error", /* bit 9, non-fatal */ 5575135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5585135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Bad TLP", /* bit 11, non-fatal */ 5595135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Bad DLLP", /* bit 12, non-fatal */ 5605135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "REPLAY_NUM Rollover", /* bit 13, non-fatal */ 5615135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5625135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Replay Timer Timeout", /* bit 15, non-fatal */ 5635135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5645135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5655135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5665135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Data Link Protocol Error", /* bit 19, fatal */ 5675135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5685135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Poisoned TLP", /* bit 21, non-fatal */ 5695135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5705135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Completion Timeout", /* bit 23, non-fatal */ 5715135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Completer Abort", /* bit 24, non-fatal */ 5725135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Unexpected Completion", /* bit 25, non-fatal */ 5735135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Receiver Overflow", /* bit 26, fatal */ 5745135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Malformed TLP", /* bit 27, fatal */ 5755135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "", /* reserved */ 5765135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov "Unsupported Request" /* bit 29, non-fatal */ 5775135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov}; 5785135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 5795135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalovstatic void do_nsi_error(int fatal, u32 errors) 5805135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov{ 5815135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov int i; 5825135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 5835135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov for (i = 0; i < 30; i++) { 5845135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (errors & (1 << i)) 5855135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov printk(KERN_WARNING "%sError %s\n", 5865135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov fatal_message[fatal], nsi_message[i]); 5875135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } 5885135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov} 5895135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 5905135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalovstatic inline void nsi_error(int fatal, u32 errors, int *error_found, 5915135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov int handle_error) 5925135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov{ 5935135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov *error_found = 1; 5945135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 5955135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (handle_error) 5965135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov do_nsi_error(fatal, errors); 5975135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov} 5985135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 599da9bb1d27b21cb24cbb6a2efb5d3c464d357a01eAlan Coxstatic char *membuf_message[4] = { 600806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Internal PMWB to DRAM parity", 601806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Internal PMWB to System Bus Parity", 602806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Internal System Bus or IO to PMWB Parity", 603806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Internal DRAM to PMWB Parity" 604806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 605806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 606806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void do_membuf_error(u8 errors) 607806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 608806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int i; 609806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 610806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox for (i = 0; i < 4; i++) { 611806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (errors & (1 << i)) 612537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_printk(KERN_WARNING, "Non-Fatal Error %s\n", 613052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson membuf_message[i]); 614806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 615806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 616806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 617806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void membuf_error(u8 errors, int *error_found, int handle_error) 618806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 619806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 620806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 621806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 622806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox do_membuf_error(errors); 623806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 624806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 625e009356f738634d8a137cca35503b9b33322c858Dave Petersonstatic char *sysbus_message[10] = { 626806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Addr or Request Parity", 627806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Data Strobe Glitch", 628806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Addr Strobe Glitch", 629806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Data Parity", 630806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Addr Above TOM", 631806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Non DRAM Lock Error", 632806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "MCERR", "BINIT", 633806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "Memory Parity", 634806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox "IO Subsystem Parity" 635806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 636806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 637806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void do_sysbus_error(int fatal, u32 errors) 638806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 639806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int i; 640806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 641806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox for (i = 0; i < 10; i++) { 642806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (errors & (1 << i)) 643537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_printk(KERN_WARNING, "%sError System Bus %s\n", 644052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson fatal_message[fatal], sysbus_message[i]); 645806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 646806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 647806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 648806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic inline void sysbus_error(int fatal, u32 errors, int *error_found, 649203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang int handle_error) 650806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 651806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox *error_found = 1; 652806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 653806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (handle_error) 654806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox do_sysbus_error(fatal, errors); 655806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 656806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 657e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Petersonstatic void e752x_check_hub_interface(struct e752x_error_info *info, 658052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int *error_found, int handle_error) 659806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 660806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u8 stat8; 661806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 662806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox //pci_read_config_byte(dev,E752X_HI_FERR,&stat8); 663e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 664806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 = info->hi_ferr; 665e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 666203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat8 & 0x7f) { /* Error, so process */ 667806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 &= 0x7f; 668e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 669203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat8 & 0x2b) 670806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox hub_error(1, stat8 & 0x2b, error_found, handle_error); 671e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 672203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat8 & 0x54) 673806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox hub_error(0, stat8 & 0x54, error_found, handle_error); 674806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 675806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox //pci_read_config_byte(dev,E752X_HI_NERR,&stat8); 676e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 677806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 = info->hi_nerr; 678e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 679203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat8 & 0x7f) { /* Error, so process */ 680806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 &= 0x7f; 681e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 682806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (stat8 & 0x2b) 683806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox hub_error(1, stat8 & 0x2b, error_found, handle_error); 684e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 685203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat8 & 0x54) 686806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox hub_error(0, stat8 & 0x54, error_found, handle_error); 687806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 688806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 689806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 6905135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalovstatic void e752x_check_ns_interface(struct e752x_error_info *info, 6915135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov int *error_found, int handle_error) 6925135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov{ 6935135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov u32 stat32; 6945135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 6955135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov stat32 = info->nsi_ferr; 6965135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (stat32 & NSI_ERR_MASK) { /* Error, so process */ 6975135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (stat32 & NSI_FATAL_MASK) /* check for fatal errors */ 6985135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov nsi_error(1, stat32 & NSI_FATAL_MASK, error_found, 6995135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov handle_error); 7005135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (stat32 & NSI_NON_FATAL_MASK) /* check for non-fatal ones */ 7015135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found, 7025135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov handle_error); 7035135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } 7045135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov stat32 = info->nsi_nerr; 7055135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (stat32 & NSI_ERR_MASK) { 7065135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (stat32 & NSI_FATAL_MASK) 7075135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov nsi_error(1, stat32 & NSI_FATAL_MASK, error_found, 7085135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov handle_error); 7095135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (stat32 & NSI_NON_FATAL_MASK) 7105135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found, 7115135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov handle_error); 7125135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } 7135135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov} 7145135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 715e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Petersonstatic void e752x_check_sysbus(struct e752x_error_info *info, 716052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int *error_found, int handle_error) 717806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 718806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 stat32, error32; 719806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 720806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox //pci_read_config_dword(dev,E752X_SYSBUS_FERR,&stat32); 721806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat32 = info->sysbus_ferr + (info->sysbus_nerr << 16); 722806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 723806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (stat32 == 0) 724203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang return; /* no errors */ 725806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 726806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error32 = (stat32 >> 16) & 0x3ff; 727806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat32 = stat32 & 0x3ff; 728e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 729203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat32 & 0x087) 730dfb2a76378f095b0aaa2024ce9a8cfb2ae2354d2Brian Pomerantz sysbus_error(1, stat32 & 0x087, error_found, handle_error); 731e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 732203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat32 & 0x378) 733dfb2a76378f095b0aaa2024ce9a8cfb2ae2354d2Brian Pomerantz sysbus_error(0, stat32 & 0x378, error_found, handle_error); 734e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 735203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error32 & 0x087) 736dfb2a76378f095b0aaa2024ce9a8cfb2ae2354d2Brian Pomerantz sysbus_error(1, error32 & 0x087, error_found, handle_error); 737e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 738203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error32 & 0x378) 739dfb2a76378f095b0aaa2024ce9a8cfb2ae2354d2Brian Pomerantz sysbus_error(0, error32 & 0x378, error_found, handle_error); 740806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 741806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 742203333cbbaae3941504c2b6e92850783bf361b6fDave Jiangstatic void e752x_check_membuf(struct e752x_error_info *info, 743052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int *error_found, int handle_error) 744806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 745806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u8 stat8; 746806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 747806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 = info->buf_ferr; 748e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 749203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat8 & 0x0f) { /* Error, so process */ 750806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 &= 0x0f; 751806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox membuf_error(stat8, error_found, handle_error); 752806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 753e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 754806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 = info->buf_nerr; 755e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 756203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (stat8 & 0x0f) { /* Error, so process */ 757806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 &= 0x0f; 758806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox membuf_error(stat8, error_found, handle_error); 759806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 760806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 761806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 762203333cbbaae3941504c2b6e92850783bf361b6fDave Jiangstatic void e752x_check_dram(struct mem_ctl_info *mci, 763052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson struct e752x_error_info *info, int *error_found, 764052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int handle_error) 765806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 766806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 error_one, error_next; 767806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 768806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error_one = info->dram_ferr; 769806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error_next = info->dram_nerr; 770806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 771806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* decode and report errors */ 772203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_one & 0x0101) /* check first error correctable */ 773806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ce(mci, error_one, info->dram_sec1_add, 774052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->dram_sec1_syndrome, error_found, handle_error); 775806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 776203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_next & 0x0101) /* check next error correctable */ 777806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ce(mci, error_next, info->dram_sec2_add, 778052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->dram_sec2_syndrome, error_found, handle_error); 779806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 780203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_one & 0x4040) 781806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ue_no_info_wr(mci, error_found, handle_error); 782806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 783203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_next & 0x4040) 784806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ue_no_info_wr(mci, error_found, handle_error); 785806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 786203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_one & 0x2020) 787806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ded_retry(mci, error_one, info->dram_retr_add, 788052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson error_found, handle_error); 789806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 790203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_next & 0x2020) 791806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ded_retry(mci, error_next, info->dram_retr_add, 792052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson error_found, handle_error); 793806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 794203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_one & 0x0808) 795203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang process_threshold_ce(mci, error_one, error_found, handle_error); 796806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 797203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_next & 0x0808) 798806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_threshold_ce(mci, error_next, error_found, 799052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson handle_error); 800806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 801203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_one & 0x0606) 802806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ue(mci, error_one, info->dram_ded_add, 803052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->dram_scrb_add, error_found, handle_error); 804806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 805203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (error_next & 0x0606) 806806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox process_ue(mci, error_next, info->dram_ded_add, 807052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->dram_scrb_add, error_found, handle_error); 808806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 809806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 810203333cbbaae3941504c2b6e92850783bf361b6fDave Jiangstatic void e752x_get_error_info(struct mem_ctl_info *mci, 811203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang struct e752x_error_info *info) 812806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 813806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct pci_dev *dev; 814806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct e752x_pvt *pvt; 815806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 816806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox memset(info, 0, sizeof(*info)); 817203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang pvt = (struct e752x_pvt *)mci->pvt_info; 818806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox dev = pvt->dev_d0f1; 819806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global); 820806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 821806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->ferr_global) { 8225135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) { 8235135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_read_config_dword(dev, I3100_NSI_FERR, 8245135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov &info->nsi_ferr); 8255135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov info->hi_ferr = 0; 8265135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } else { 8275135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_read_config_byte(dev, E752X_HI_FERR, 8285135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov &info->hi_ferr); 8295135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov info->nsi_ferr = 0; 8305135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } 831806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_word(dev, E752X_SYSBUS_FERR, 832052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->sysbus_ferr); 833806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr); 834203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang pci_read_config_word(dev, E752X_DRAM_FERR, &info->dram_ferr); 835806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_dword(dev, E752X_DRAM_SEC1_ADD, 836052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->dram_sec1_add); 837806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_word(dev, E752X_DRAM_SEC1_SYNDROME, 838052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->dram_sec1_syndrome); 839806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_dword(dev, E752X_DRAM_DED_ADD, 840052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->dram_ded_add); 841806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_dword(dev, E752X_DRAM_SCRB_ADD, 842052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->dram_scrb_add); 843806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_dword(dev, E752X_DRAM_RETR_ADD, 844052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->dram_retr_add); 845806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 8465135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov /* ignore the reserved bits just in case */ 847806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->hi_ferr & 0x7f) 848806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_byte(dev, E752X_HI_FERR, 849052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->hi_ferr); 850806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 8515135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (info->nsi_ferr & NSI_ERR_MASK) 8525135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_write_config_dword(dev, I3100_NSI_FERR, 8535135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov info->nsi_ferr); 8545135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 855806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->sysbus_ferr) 856806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_word(dev, E752X_SYSBUS_FERR, 857052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->sysbus_ferr); 858806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 859806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->buf_ferr & 0x0f) 860806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_byte(dev, E752X_BUF_FERR, 861052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->buf_ferr); 862806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 863806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->dram_ferr) 864806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR, 865203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang info->dram_ferr, info->dram_ferr); 866806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 867806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_dword(dev, E752X_FERR_GLOBAL, 868052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->ferr_global); 869806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 870806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 871806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global); 872806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 873806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->nerr_global) { 8745135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) { 8755135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_read_config_dword(dev, I3100_NSI_NERR, 8765135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov &info->nsi_nerr); 8775135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov info->hi_nerr = 0; 8785135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } else { 8795135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_read_config_byte(dev, E752X_HI_NERR, 8805135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov &info->hi_nerr); 8815135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov info->nsi_nerr = 0; 8825135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } 883806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_word(dev, E752X_SYSBUS_NERR, 884052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->sysbus_nerr); 885806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr); 886203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang pci_read_config_word(dev, E752X_DRAM_NERR, &info->dram_nerr); 887806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_dword(dev, E752X_DRAM_SEC2_ADD, 888052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->dram_sec2_add); 889806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_word(dev, E752X_DRAM_SEC2_SYNDROME, 890052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &info->dram_sec2_syndrome); 891806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 892806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->hi_nerr & 0x7f) 893806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_byte(dev, E752X_HI_NERR, 894052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->hi_nerr); 895806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 8965135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (info->nsi_nerr & NSI_ERR_MASK) 8975135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_write_config_dword(dev, I3100_NSI_NERR, 8985135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov info->nsi_nerr); 8995135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov 900806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->sysbus_nerr) 901806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_word(dev, E752X_SYSBUS_NERR, 902052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->sysbus_nerr); 903806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 904806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->buf_nerr & 0x0f) 905806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_byte(dev, E752X_BUF_NERR, 906052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->buf_nerr); 907806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 908806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (info->dram_nerr) 909806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR, 910203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang info->dram_nerr, info->dram_nerr); 911806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 912806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_dword(dev, E752X_NERR_GLOBAL, 913052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson info->nerr_global); 914806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 915806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 916806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 917203333cbbaae3941504c2b6e92850783bf361b6fDave Jiangstatic int e752x_process_error_info(struct mem_ctl_info *mci, 918052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson struct e752x_error_info *info, 919052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int handle_errors) 920806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 921806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u32 error32, stat32; 922806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int error_found; 923806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 924806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error_found = 0; 925806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error32 = (info->ferr_global >> 18) & 0x3ff; 926806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat32 = (info->ferr_global >> 4) & 0x7ff; 927806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 928806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (error32) 929806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox global_error(1, error32, &error_found, handle_errors); 930806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 931806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (stat32) 932806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox global_error(0, stat32, &error_found, handle_errors); 933806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 934806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox error32 = (info->nerr_global >> 18) & 0x3ff; 935806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat32 = (info->nerr_global >> 4) & 0x7ff; 936806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 937806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (error32) 938806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox global_error(1, error32, &error_found, handle_errors); 939806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 940806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (stat32) 941806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox global_error(0, stat32, &error_found, handle_errors); 942806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 943806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox e752x_check_hub_interface(info, &error_found, handle_errors); 9445135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov e752x_check_ns_interface(info, &error_found, handle_errors); 945806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox e752x_check_sysbus(info, &error_found, handle_errors); 946806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox e752x_check_membuf(info, &error_found, handle_errors); 947806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox e752x_check_dram(mci, info, &error_found, handle_errors); 948806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return error_found; 949806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 950806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 951806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void e752x_check(struct mem_ctl_info *mci) 952806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 953806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct e752x_error_info info; 954e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 955537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 956806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox e752x_get_error_info(mci, &info); 957806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox e752x_process_error_info(mci, &info, 1); 958806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 959806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 9608004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser/* Program byte/sec bandwidth scrub rate to hardware */ 961eba042a81edd6baaff44831b2d719b14a6d21e58Borislav Petkovstatic int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw) 9628004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser{ 9638004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser const struct scrubrate *scrubrates; 9648004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; 9658004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser struct pci_dev *pdev = pvt->dev_d0f0; 9668004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser int i; 9678004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 9688004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0) 9698004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser scrubrates = scrubrates_i3100; 9708004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser else 9718004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser scrubrates = scrubrates_e752x; 9728004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 9738004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser /* Translate the desired scrub rate to a e752x/3100 register value. 9748004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * Search for the bandwidth that is equal or greater than the 9758004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser * desired rate and program the cooresponding register value. 9768004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser */ 9778004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++) 978eba042a81edd6baaff44831b2d719b14a6d21e58Borislav Petkov if (scrubrates[i].bandwidth >= new_bw) 9798004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser break; 9808004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 9818004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser if (scrubrates[i].bandwidth == SDRATE_EOT) 9828004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser return -1; 9838004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 9848004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); 9858004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 986390944439f746824faec51b576f50cb5ef18745bBorislav Petkov return scrubrates[i].bandwidth; 9878004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser} 9888004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 9898004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser/* Convert current scrub rate value into byte/sec bandwidth */ 990390944439f746824faec51b576f50cb5ef18745bBorislav Petkovstatic int get_sdram_scrub_rate(struct mem_ctl_info *mci) 9918004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser{ 9928004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser const struct scrubrate *scrubrates; 9938004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; 9948004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser struct pci_dev *pdev = pvt->dev_d0f0; 9958004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser u16 scrubval; 9968004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser int i; 9978004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 9988004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0) 9998004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser scrubrates = scrubrates_i3100; 10008004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser else 10018004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser scrubrates = scrubrates_e752x; 10028004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 10038004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser /* Find the bandwidth matching the memory scrubber configuration */ 10048004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser pci_read_config_word(pdev, E752X_MCHSCRB, &scrubval); 10058004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser scrubval = scrubval & 0x0f; 10068004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 10078004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++) 10088004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser if (scrubrates[i].scrubval == scrubval) 10098004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser break; 10108004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 10118004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser if (scrubrates[i].bandwidth == SDRATE_EOT) { 10128004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser e752x_printk(KERN_WARNING, 10138004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser "Invalid sdram scrub control value: 0x%x\n", scrubval); 10148004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser return -1; 10158004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser } 1016390944439f746824faec51b576f50cb5ef18745bBorislav Petkov return scrubrates[i].bandwidth; 10178004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 10188004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser} 10198004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser 10201318952514d5651c453d89989595a9df3b37267bDoug Thompson/* Return 1 if dual channel mode is active. Else return 0. */ 10211318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic inline int dual_channel_active(u16 ddrcsr) 10221318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 10231318952514d5651c453d89989595a9df3b37267bDoug Thompson return (((ddrcsr >> 12) & 3) == 3); 10241318952514d5651c453d89989595a9df3b37267bDoug Thompson} 10251318952514d5651c453d89989595a9df3b37267bDoug Thompson 10267297c2617f6465d7862e156d4db5d812744280f1Mark Grondona/* Remap csrow index numbers if map_type is "reverse" 10277297c2617f6465d7862e156d4db5d812744280f1Mark Grondona */ 10287297c2617f6465d7862e156d4db5d812744280f1Mark Grondonastatic inline int remap_csrow_index(struct mem_ctl_info *mci, int index) 10297297c2617f6465d7862e156d4db5d812744280f1Mark Grondona{ 10307297c2617f6465d7862e156d4db5d812744280f1Mark Grondona struct e752x_pvt *pvt = mci->pvt_info; 10317297c2617f6465d7862e156d4db5d812744280f1Mark Grondona 10327297c2617f6465d7862e156d4db5d812744280f1Mark Grondona if (!pvt->map_type) 10337297c2617f6465d7862e156d4db5d812744280f1Mark Grondona return (7 - index); 10347297c2617f6465d7862e156d4db5d812744280f1Mark Grondona 10357297c2617f6465d7862e156d4db5d812744280f1Mark Grondona return (index); 10367297c2617f6465d7862e156d4db5d812744280f1Mark Grondona} 10377297c2617f6465d7862e156d4db5d812744280f1Mark Grondona 10381318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, 1039052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson u16 ddrcsr) 10401318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 10411318952514d5651c453d89989595a9df3b37267bDoug Thompson struct csrow_info *csrow; 10421318952514d5651c453d89989595a9df3b37267bDoug Thompson unsigned long last_cumul_size; 10431318952514d5651c453d89989595a9df3b37267bDoug Thompson int index, mem_dev, drc_chan; 1044203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ 1045203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang int drc_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */ 10461318952514d5651c453d89989595a9df3b37267bDoug Thompson u8 value; 10471318952514d5651c453d89989595a9df3b37267bDoug Thompson u32 dra, drc, cumul_size; 10481318952514d5651c453d89989595a9df3b37267bDoug Thompson 10499962fd017becf944d671da498ccaaea570452206Brian Pomerantz dra = 0; 1050203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang for (index = 0; index < 4; index++) { 10519962fd017becf944d671da498ccaaea570452206Brian Pomerantz u8 dra_reg; 1052203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang pci_read_config_byte(pdev, E752X_DRA + index, &dra_reg); 10539962fd017becf944d671da498ccaaea570452206Brian Pomerantz dra |= dra_reg << (index * 8); 10549962fd017becf944d671da498ccaaea570452206Brian Pomerantz } 10551318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_read_config_dword(pdev, E752X_DRC, &drc); 10561318952514d5651c453d89989595a9df3b37267bDoug Thompson drc_chan = dual_channel_active(ddrcsr); 1057203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */ 10581318952514d5651c453d89989595a9df3b37267bDoug Thompson drc_ddim = (drc >> 20) & 0x3; 10591318952514d5651c453d89989595a9df3b37267bDoug Thompson 10601318952514d5651c453d89989595a9df3b37267bDoug Thompson /* The dram row boundary (DRB) reg values are boundary address for 10611318952514d5651c453d89989595a9df3b37267bDoug Thompson * each DRAM row with a granularity of 64 or 128MB (single/dual 10621318952514d5651c453d89989595a9df3b37267bDoug Thompson * channel operation). DRB regs are cumulative; therefore DRB7 will 10631318952514d5651c453d89989595a9df3b37267bDoug Thompson * contain the total memory contained in all eight rows. 10641318952514d5651c453d89989595a9df3b37267bDoug Thompson */ 10651318952514d5651c453d89989595a9df3b37267bDoug Thompson for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { 10661318952514d5651c453d89989595a9df3b37267bDoug Thompson /* mem_dev 0=x8, 1=x4 */ 10671318952514d5651c453d89989595a9df3b37267bDoug Thompson mem_dev = (dra >> (index * 4 + 2)) & 0x3; 10687297c2617f6465d7862e156d4db5d812744280f1Mark Grondona csrow = &mci->csrows[remap_csrow_index(mci, index)]; 10691318952514d5651c453d89989595a9df3b37267bDoug Thompson 10701318952514d5651c453d89989595a9df3b37267bDoug Thompson mem_dev = (mem_dev == 2); 10711318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_read_config_byte(pdev, E752X_DRB + index, &value); 10721318952514d5651c453d89989595a9df3b37267bDoug Thompson /* convert a 128 or 64 MiB DRB to a page size. */ 10731318952514d5651c453d89989595a9df3b37267bDoug Thompson cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); 10741318952514d5651c453d89989595a9df3b37267bDoug Thompson debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, 10751318952514d5651c453d89989595a9df3b37267bDoug Thompson cumul_size); 10761318952514d5651c453d89989595a9df3b37267bDoug Thompson if (cumul_size == last_cumul_size) 10771318952514d5651c453d89989595a9df3b37267bDoug Thompson continue; /* not populated */ 10781318952514d5651c453d89989595a9df3b37267bDoug Thompson 10791318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->first_page = last_cumul_size; 10801318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->last_page = cumul_size - 1; 10811318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->nr_pages = cumul_size - last_cumul_size; 10821318952514d5651c453d89989595a9df3b37267bDoug Thompson last_cumul_size = cumul_size; 10831318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ 10841318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->mtype = MEM_RDDR; /* only one type supported */ 10851318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; 10861318952514d5651c453d89989595a9df3b37267bDoug Thompson 10871318952514d5651c453d89989595a9df3b37267bDoug Thompson /* 10881318952514d5651c453d89989595a9df3b37267bDoug Thompson * if single channel or x8 devices then SECDED 10891318952514d5651c453d89989595a9df3b37267bDoug Thompson * if dual channel and x4 then S4ECD4ED 10901318952514d5651c453d89989595a9df3b37267bDoug Thompson */ 10911318952514d5651c453d89989595a9df3b37267bDoug Thompson if (drc_ddim) { 10921318952514d5651c453d89989595a9df3b37267bDoug Thompson if (drc_chan && mem_dev) { 10931318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->edac_mode = EDAC_S4ECD4ED; 10941318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->edac_cap |= EDAC_FLAG_S4ECD4ED; 10951318952514d5651c453d89989595a9df3b37267bDoug Thompson } else { 10961318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->edac_mode = EDAC_SECDED; 10971318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->edac_cap |= EDAC_FLAG_SECDED; 10981318952514d5651c453d89989595a9df3b37267bDoug Thompson } 10991318952514d5651c453d89989595a9df3b37267bDoug Thompson } else 11001318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->edac_mode = EDAC_NONE; 11011318952514d5651c453d89989595a9df3b37267bDoug Thompson } 11021318952514d5651c453d89989595a9df3b37267bDoug Thompson} 11031318952514d5651c453d89989595a9df3b37267bDoug Thompson 11041318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic void e752x_init_mem_map_table(struct pci_dev *pdev, 1105052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson struct e752x_pvt *pvt) 1106806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 1107806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int index; 11087297c2617f6465d7862e156d4db5d812744280f1Mark Grondona u8 value, last, row; 11091318952514d5651c453d89989595a9df3b37267bDoug Thompson 11101318952514d5651c453d89989595a9df3b37267bDoug Thompson last = 0; 11111318952514d5651c453d89989595a9df3b37267bDoug Thompson row = 0; 11121318952514d5651c453d89989595a9df3b37267bDoug Thompson 11131318952514d5651c453d89989595a9df3b37267bDoug Thompson for (index = 0; index < 8; index += 2) { 11141318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_read_config_byte(pdev, E752X_DRB + index, &value); 11151318952514d5651c453d89989595a9df3b37267bDoug Thompson /* test if there is a dimm in this slot */ 11161318952514d5651c453d89989595a9df3b37267bDoug Thompson if (value == last) { 11171318952514d5651c453d89989595a9df3b37267bDoug Thompson /* no dimm in the slot, so flag it as empty */ 11181318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->map[index] = 0xff; 11191318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->map[index + 1] = 0xff; 1120203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang } else { /* there is a dimm in the slot */ 11211318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->map[index] = row; 11221318952514d5651c453d89989595a9df3b37267bDoug Thompson row++; 11231318952514d5651c453d89989595a9df3b37267bDoug Thompson last = value; 11241318952514d5651c453d89989595a9df3b37267bDoug Thompson /* test the next value to see if the dimm is double 11251318952514d5651c453d89989595a9df3b37267bDoug Thompson * sided 11261318952514d5651c453d89989595a9df3b37267bDoug Thompson */ 11271318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_read_config_byte(pdev, E752X_DRB + index + 1, 1128052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson &value); 1129052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson 1130052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson /* the dimm is single sided, so flag as empty */ 1131052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson /* this is a double sided dimm to save the next row #*/ 1132052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson pvt->map[index + 1] = (value == last) ? 0xff : row; 11331318952514d5651c453d89989595a9df3b37267bDoug Thompson row++; 11341318952514d5651c453d89989595a9df3b37267bDoug Thompson last = value; 11351318952514d5651c453d89989595a9df3b37267bDoug Thompson } 11361318952514d5651c453d89989595a9df3b37267bDoug Thompson } 11371318952514d5651c453d89989595a9df3b37267bDoug Thompson} 11381318952514d5651c453d89989595a9df3b37267bDoug Thompson 11391318952514d5651c453d89989595a9df3b37267bDoug Thompson/* Return 0 on success or 1 on failure. */ 11401318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic int e752x_get_devs(struct pci_dev *pdev, int dev_idx, 1141052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson struct e752x_pvt *pvt) 11421318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 11431318952514d5651c453d89989595a9df3b37267bDoug Thompson struct pci_dev *dev; 11441318952514d5651c453d89989595a9df3b37267bDoug Thompson 11451318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, 114610d33e9c36827e5371479e55ef4089e000af2638Doug Thompson pvt->dev_info->err_dev, pvt->bridge_ck); 11471318952514d5651c453d89989595a9df3b37267bDoug Thompson 11481318952514d5651c453d89989595a9df3b37267bDoug Thompson if (pvt->bridge_ck == NULL) 11491318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->bridge_ck = pci_scan_single_device(pdev->bus, 11501318952514d5651c453d89989595a9df3b37267bDoug Thompson PCI_DEVFN(0, 1)); 11511318952514d5651c453d89989595a9df3b37267bDoug Thompson 11521318952514d5651c453d89989595a9df3b37267bDoug Thompson if (pvt->bridge_ck == NULL) { 11531318952514d5651c453d89989595a9df3b37267bDoug Thompson e752x_printk(KERN_ERR, "error reporting device not found:" 1154052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "vendor %x device 0x%x (broken BIOS?)\n", 1155052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); 11561318952514d5651c453d89989595a9df3b37267bDoug Thompson return 1; 11571318952514d5651c453d89989595a9df3b37267bDoug Thompson } 11581318952514d5651c453d89989595a9df3b37267bDoug Thompson 115910d33e9c36827e5371479e55ef4089e000af2638Doug Thompson dev = pci_get_device(PCI_VENDOR_ID_INTEL, 116010d33e9c36827e5371479e55ef4089e000af2638Doug Thompson e752x_devs[dev_idx].ctl_dev, 116110d33e9c36827e5371479e55ef4089e000af2638Doug Thompson NULL); 11621318952514d5651c453d89989595a9df3b37267bDoug Thompson 11631318952514d5651c453d89989595a9df3b37267bDoug Thompson if (dev == NULL) 11641318952514d5651c453d89989595a9df3b37267bDoug Thompson goto fail; 11651318952514d5651c453d89989595a9df3b37267bDoug Thompson 11661318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->dev_d0f0 = dev; 11671318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck); 11681318952514d5651c453d89989595a9df3b37267bDoug Thompson 11691318952514d5651c453d89989595a9df3b37267bDoug Thompson return 0; 11701318952514d5651c453d89989595a9df3b37267bDoug Thompson 1171052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail: 11721318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_dev_put(pvt->bridge_ck); 11731318952514d5651c453d89989595a9df3b37267bDoug Thompson return 1; 11741318952514d5651c453d89989595a9df3b37267bDoug Thompson} 11751318952514d5651c453d89989595a9df3b37267bDoug Thompson 117694ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser/* Setup system bus parity mask register. 117794ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser * Sysbus parity supported on: 11788de5c1a165be5624a1003ce17877299e04b2afd6Konstantin Olifer * e7320/e7520/e7525 + Xeon 117994ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser */ 118094ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyserstatic void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt) 118194ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser{ 118294ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser char *cpu_id = cpu_data(0).x86_model_id; 118394ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser struct pci_dev *dev = pvt->dev_d0f1; 118494ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser int enable = 1; 118594ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser 118698a1708de1bfa5fe1c490febba850d6043d3c7faMartin Olsson /* Allow module parameter override, else see if CPU supports parity */ 118794ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser if (sysbus_parity != -1) { 118894ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser enable = sysbus_parity; 11898de5c1a165be5624a1003ce17877299e04b2afd6Konstantin Olifer } else if (cpu_id[0] && !strstr(cpu_id, "Xeon")) { 119094ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser e752x_printk(KERN_INFO, "System Bus Parity not " 119194ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser "supported by CPU, disabling\n"); 119294ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser enable = 0; 119394ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser } 119494ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser 119594ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser if (enable) 119694ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0000); 119794ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser else 119894ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0309); 119994ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser} 120094ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser 12011318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic void e752x_init_error_reporting_regs(struct e752x_pvt *pvt) 12021318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 12031318952514d5651c453d89989595a9df3b37267bDoug Thompson struct pci_dev *dev; 12041318952514d5651c453d89989595a9df3b37267bDoug Thompson 12051318952514d5651c453d89989595a9df3b37267bDoug Thompson dev = pvt->dev_d0f1; 12061318952514d5651c453d89989595a9df3b37267bDoug Thompson /* Turn off error disable & SMI in case the BIOS turned it on */ 12075135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) { 12085135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_write_config_dword(dev, I3100_NSI_EMASK, 0); 12095135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_write_config_dword(dev, I3100_NSI_SMICMD, 0); 12105135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } else { 12115135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00); 12125135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00); 12135135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov } 121494ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser 121594ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser e752x_init_sysbus_parity_mask(pvt); 121694ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser 12171318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00); 12181318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00); 12191318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00); 12201318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00); 12211318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00); 12221318952514d5651c453d89989595a9df3b37267bDoug Thompson} 12231318952514d5651c453d89989595a9df3b37267bDoug Thompson 12241318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic int e752x_probe1(struct pci_dev *pdev, int dev_idx) 12251318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 12263847bccce80c8a01d7adbad9961564252207302aDave Peterson u16 pci_data; 1227806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u8 stat8; 12281318952514d5651c453d89989595a9df3b37267bDoug Thompson struct mem_ctl_info *mci; 12291318952514d5651c453d89989595a9df3b37267bDoug Thompson struct e752x_pvt *pvt; 1230806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox u16 ddrcsr; 1231203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang int drc_chan; /* Number of channels 0=1chan,1=2chan */ 1232749ede57443b2a7ede2db105145f21047efcea6aDave Peterson struct e752x_error_info discard; 1233806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1234537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf0("%s(): mci\n", __func__); 1235806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox debugf0("Starting Probe1\n"); 1236806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 123796941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross /* check to see if device 0 function 1 is enabled; if it isn't, we 123896941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross * assume the BIOS has reserved it for a reason and is expecting 123996941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross * exclusive access, we take care not to violate that assumption and 124096941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross * fail the probe. */ 1241806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8); 124296941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross if (!force_function_unhide && !(stat8 & (1 << 5))) { 124396941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross printk(KERN_INFO "Contact your BIOS vendor to see if the " 1244052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "E752x error registers can be safely un-hidden\n"); 1245f9b5a5d193c3f0bc2a8331d95e0e74d76eb8ee2cAristeu Rozanski return -ENODEV; 124696941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross } 1247806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox stat8 |= (1 << 5); 1248806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_write_config_byte(pdev, E752X_DEVPRES1, stat8); 1249806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1250806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr); 1251806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* FIXME: should check >>12 or 0xf, true for all? */ 1252806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* Dual channel = 1, Single channel = 0 */ 12531318952514d5651c453d89989595a9df3b37267bDoug Thompson drc_chan = dual_channel_active(ddrcsr); 1254806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1255b8f6f9755248026f21282e25cac49a1af698056cDoug Thompson mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1, 0); 1256806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1257806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox if (mci == NULL) { 12581318952514d5651c453d89989595a9df3b37267bDoug Thompson return -ENOMEM; 1259806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 1260806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1261537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): init mci\n", __func__); 1262806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox mci->mtype_cap = MEM_FLAG_RDDR; 12635135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov /* 3100 IMCH supports SECDEC only */ 12645135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED : 12655135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov (EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED); 1266806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* FIXME - what if different memory types are in different csrows? */ 1267680cbbbb0e336b04b74be48b8ddd870537f1e226Dave Peterson mci->mod_name = EDAC_MOD_STR; 126837f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson mci->mod_ver = E752X_REVISION; 126937f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson mci->dev = &pdev->dev; 1270806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1271537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): init pvt\n", __func__); 1272203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang pvt = (struct e752x_pvt *)mci->pvt_info; 1273806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pvt->dev_info = &e752x_devs[dev_idx]; 12741318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); 1275e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 12761318952514d5651c453d89989595a9df3b37267bDoug Thompson if (e752x_get_devs(pdev, dev_idx, pvt)) { 12771318952514d5651c453d89989595a9df3b37267bDoug Thompson edac_mc_free(mci); 12781318952514d5651c453d89989595a9df3b37267bDoug Thompson return -ENODEV; 1279806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 1280806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1281537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): more mci init\n", __func__); 1282806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox mci->ctl_name = pvt->dev_info->ctl_name; 1283c4192705fec85219086231a1c0fa61e8776e2c3bDave Jiang mci->dev_name = pci_name(pdev); 1284806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox mci->edac_check = e752x_check; 1285806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox mci->ctl_page_to_phys = ctl_page_to_phys; 12868004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser mci->set_sdram_scrub_rate = set_sdram_scrub_rate; 12878004fd2ad6042ae24d3913cf5089909781db3a25Peter Tyser mci->get_sdram_scrub_rate = get_sdram_scrub_rate; 1288806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 12897297c2617f6465d7862e156d4db5d812744280f1Mark Grondona /* set the map type. 1 = normal, 0 = reversed 12907297c2617f6465d7862e156d4db5d812744280f1Mark Grondona * Must be set before e752x_init_csrows in case csrow mapping 12917297c2617f6465d7862e156d4db5d812744280f1Mark Grondona * is reversed. 12927297c2617f6465d7862e156d4db5d812744280f1Mark Grondona */ 129337f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_byte(pdev, E752X_DRM, &stat8); 1294806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f)); 1295806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 12967297c2617f6465d7862e156d4db5d812744280f1Mark Grondona e752x_init_csrows(mci, pdev, ddrcsr); 12977297c2617f6465d7862e156d4db5d812744280f1Mark Grondona e752x_init_mem_map_table(pdev, pvt); 12987297c2617f6465d7862e156d4db5d812744280f1Mark Grondona 12995135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov if (dev_idx == I3100) 13005135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */ 13015135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov else 13025135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov mci->edac_cap |= EDAC_FLAG_NONE; 1303537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); 1304e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 1305806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* load the top of low memory, remap base, and remap limit vars */ 130637f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_word(pdev, E752X_TOLM, &pci_data); 1307806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pvt->tolm = ((u32) pci_data) << 4; 130837f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_word(pdev, E752X_REMAPBASE, &pci_data); 1309806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pvt->remapbase = ((u32) pci_data) << 14; 131037f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_word(pdev, E752X_REMAPLIMIT, &pci_data); 1311806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pvt->remaplimit = ((u32) pci_data) << 14; 1312537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson e752x_printk(KERN_INFO, 1313052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "tolm = %x, remapbase = %x, remaplimit = %x\n", 1314052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson pvt->tolm, pvt->remapbase, pvt->remaplimit); 1315806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 13162d7bbb91c8df26c60d223205a087507430024177Doug Thompson /* Here we assume that we will never see multiple instances of this 13172d7bbb91c8df26c60d223205a087507430024177Doug Thompson * type of memory controller. The ID is therefore hardcoded to 0. 13182d7bbb91c8df26c60d223205a087507430024177Doug Thompson */ 1319b8f6f9755248026f21282e25cac49a1af698056cDoug Thompson if (edac_mc_add_mc(mci)) { 1320537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): failed edac_mc_add_mc()\n", __func__); 1321806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox goto fail; 1322806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox } 1323806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 13241318952514d5651c453d89989595a9df3b37267bDoug Thompson e752x_init_error_reporting_regs(pvt); 1325203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang e752x_get_error_info(mci, &discard); /* clear other MCH errors */ 1326806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 132791b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang /* allocating generic PCI control info */ 132891b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang e752x_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); 132991b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang if (!e752x_pci) { 133091b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang printk(KERN_WARNING 1331052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "%s(): Unable to create PCI control\n", __func__); 133291b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang printk(KERN_WARNING 1333052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "%s(): PCI error report via EDAC not setup\n", 1334052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson __func__); 133591b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang } 133691b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang 1337806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* get this far and it's successful */ 1338537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): success\n", __func__); 1339806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return 0; 1340806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1341052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail: 13421318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_dev_put(pvt->dev_d0f0); 13431318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_dev_put(pvt->dev_d0f1); 13441318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_dev_put(pvt->bridge_ck); 13451318952514d5651c453d89989595a9df3b37267bDoug Thompson edac_mc_free(mci); 1346e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 13471318952514d5651c453d89989595a9df3b37267bDoug Thompson return -ENODEV; 1348806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 1349806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1350806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox/* returns count (>= 0), or negative on error */ 1351806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic int __devinit e752x_init_one(struct pci_dev *pdev, 1352052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson const struct pci_device_id *ent) 1353806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 1354537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf0("%s()\n", __func__); 1355806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1356806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox /* wake up and enable device */ 1357203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang if (pci_enable_device(pdev) < 0) 1358806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return -EIO; 1359e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 1360806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return e752x_probe1(pdev, ent->driver_data); 1361806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 1362806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1363806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void __devexit e752x_remove_one(struct pci_dev *pdev) 1364806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 1365806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct mem_ctl_info *mci; 1366806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox struct e752x_pvt *pvt; 1367806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1368537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf0("%s()\n", __func__); 1369806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 137091b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang if (e752x_pci) 137191b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang edac_pci_release_generic_ctl(e752x_pci); 137291b99041c1d577ded1da599ddc28cec2e07253cfDave Jiang 137337f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) 1374806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return; 1375806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1376203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang pvt = (struct e752x_pvt *)mci->pvt_info; 1377806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_dev_put(pvt->dev_d0f0); 1378806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_dev_put(pvt->dev_d0f1); 1379806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_dev_put(pvt->bridge_ck); 1380806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox edac_mc_free(mci); 1381806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 1382806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 138336c46f31df910b092aaaed27c7c616bb8e2302a1Lionel Debrouxstatic DEFINE_PCI_DEVICE_TABLE(e752x_pci_tbl) = { 1384e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson { 1385203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1386203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang E7520}, 1387e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson { 1388203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1389203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang E7525}, 1390e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson { 1391203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1392203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang E7320}, 1393e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson { 13945135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov PCI_VEND_DEV(INTEL, 3100_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13955135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov I3100}, 13965135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei Konovalov { 1397203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang 0, 1398203333cbbaae3941504c2b6e92850783bf361b6fDave Jiang } /* 0 terminated list. */ 1399806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 1400806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1401806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan CoxMODULE_DEVICE_TABLE(pci, e752x_pci_tbl); 1402806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1403806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic struct pci_driver e752x_driver = { 1404680cbbbb0e336b04b74be48b8ddd870537f1e226Dave Peterson .name = EDAC_MOD_STR, 14050d38b049fe8df77c8e9dc48d0fd84555739fbb1aRandy Dunlap .probe = e752x_init_one, 14060d38b049fe8df77c8e9dc48d0fd84555739fbb1aRandy Dunlap .remove = __devexit_p(e752x_remove_one), 14070d38b049fe8df77c8e9dc48d0fd84555739fbb1aRandy Dunlap .id_table = e752x_pci_tbl, 1408806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox}; 1409806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1410da9bb1d27b21cb24cbb6a2efb5d3c464d357a01eAlan Coxstatic int __init e752x_init(void) 1411806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 1412806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox int pci_rc; 1413806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1414537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 1415c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake 1416c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake /* Ensure that the OPSTATE is set correctly for POLL or NMI */ 1417c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake opstate_init(); 1418c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake 1419806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_rc = pci_register_driver(&e752x_driver); 1420806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox return (pci_rc < 0) ? pci_rc : 0; 1421806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 1422806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1423806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxstatic void __exit e752x_exit(void) 1424806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox{ 1425537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 1426806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox pci_unregister_driver(&e752x_driver); 1427806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox} 1428806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1429806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxmodule_init(e752x_init); 1430806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Coxmodule_exit(e752x_exit); 1431806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan Cox 1432806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan CoxMODULE_LICENSE("GPL"); 1433806c35f5057a64d3061ee4e2b1023bf6f6d328e2Alan CoxMODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n"); 14345135b797c8466eac39dc7fb4ae1fac6e7276377aAndrei KonovalovMODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers"); 143596941026a51e9cb8c2d2be7499301b7fcd9ee225mark gross 143696941026a51e9cb8c2d2be7499301b7fcd9ee225mark grossmodule_param(force_function_unhide, int, 0444); 143796941026a51e9cb8c2d2be7499301b7fcd9ee225mark grossMODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:" 143810d33e9c36827e5371479e55ef4089e000af2638Doug Thompson " 1=force unhide and hope BIOS doesn't fight driver for " 143910d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "Dev0:Fun1 access"); 1440c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake 1441c0d121720220584bba2876b032e58a076b843fa1Dave Jiangmodule_param(edac_op_state, int, 0444); 1442c0d121720220584bba2876b032e58a076b843fa1Dave JiangMODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); 144394ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser 144494ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tysermodule_param(sysbus_parity, int, 0444); 144594ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter TyserMODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking," 144694ee1cf5a88e12f5cbf8c0c78a6c18d3e043241ePeter Tyser " 1=enable system bus parity checking, default=auto-detect"); 144710d33e9c36827e5371479e55ef4089e000af2638Doug Thompsonmodule_param(report_non_memory_errors, int, 0644); 144810d33e9c36827e5371479e55ef4089e000af2638Doug ThompsonMODULE_PARM_DESC(report_non_memory_errors, "0=disable non-memory error " 144910d33e9c36827e5371479e55ef4089e000af2638Doug Thompson "reporting, 1=enable non-memory error reporting"); 1450