/*
* Intel 5400 class Memory Controllers kernel module (Seaburg)
*
* This file may be distributed under the terms of the
* GNU General Public License.
*
* Copyright (c) 2008 by:
* Ben Woodard <woodard@redhat.com>
* Mauro Carvalho Chehab <mchehab@redhat.com>
*
* Red Hat Inc. http://www.redhat.com
*
* Forked and adapted from the i5000_edac driver which was
* written by Douglas Thompson Linux Networx <norsk5@xmission.com>
*
* This module is based on the following document:
*
* Intel 5400 Chipset Memory Controller Hub (MCH) - Datasheet
* http://developer.intel.com/design/chipsets/datashts/313070.htm
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/edac.h>
#include <linux/mmzone.h>
#include "edac_core.h"
/*
* Alter this version for the I5400 module when modifications are made
*/
#define I5400_REVISION " Ver: 1.0.0"
#define EDAC_MOD_STR "i5400_edac"
#define i5400_printk(level, fmt, arg...) \
edac_printk(level, "i5400", fmt, ##arg)
#define i5400_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "i5400", fmt, ##arg)
/* Limits for i5400 */
#define NUM_MTRS_PER_BRANCH 4
#define CHANNELS_PER_BRANCH 2
#define MAX_DIMMS_PER_CHANNEL NUM_MTRS_PER_BRANCH
#define MAX_CHANNELS 4
/* max possible csrows per channel */
#define MAX_CSROWS (MAX_DIMMS_PER_CHANNEL)
/* Device 16,
* Function 0: System Address
* Function 1: Memory Branch Map, Control, Errors Register
* Function 2: FSB Error Registers
*
* All 3 functions of Device 16 (0,1,2) share the SAME DID and
* uses PCI_DEVICE_ID_INTEL_5400_ERR for device 16 (0,1,2),
* PCI_DEVICE_ID_INTEL_5400_FBD0 and PCI_DEVICE_ID_INTEL_5400_FBD1
* for device 21 (0,1).
*/
/* OFFSETS for Function 0 */
#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */
#define MAXCH 0x56 /* Max Channel Number */
#define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */
/* OFFSETS for Function 1 */
#define TOLM 0x6C
#define REDMEMB 0x7C
#define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3fe00) /* bits [17:9] indicate ODD, [8:0] indicate EVEN */
#define MIR0 0x80
#define MIR1 0x84
#define AMIR0 0x8c
#define AMIR1 0x90
/* Fatal error registers */
#define FERR_FAT_FBD 0x98 /* also called as FERR_FAT_FB_DIMM at datasheet */
#define FERR_FAT_FBDCHAN (3<<28) /* channel index where the highest-order error occurred */
#define NERR_FAT_FBD 0x9c
#define FERR_NF_FBD 0xa0 /* also called as FERR_NFAT_FB_DIMM at datasheet */
/* Non-fatal error register */
#define NERR_NF_FBD 0xa4
/* Enable error mask */
#define EMASK_FBD 0xa8
#define ERR0_FBD 0xac
#define ERR1_FBD 0xb0
#define ERR2_FBD 0xb4
#define MCERR_FBD 0xb8
/* No OFFSETS for Device 16 Function 2 */
/*
* Device 21,
* Function 0: Memory Map Branch 0
*
* Device 22,
* Function 0: Memory Map Branch 1
*/
/* OFFSETS for Function 0 */
#define AMBPRESENT_0 0x64
#define AMBPRESENT_1 0x66
#defi