/*
* 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
*
* 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
*
* This Memory Controller manages DDR2 FB-DIMMs. It has 2 branches, each with
* 2 channels operating in lockstep no-mirror mode. Each channel can have up to
* 4 dimm's, each with up to 8GB.
*
*/
#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 MAX_BRANCHES 2
#define CHANNELS_PER_BRANCH 2
#define DIMMS_PER_CHANNEL 4
#define MAX_CHANNELS (MAX_BRANCHES * CHANNELS_PER_BRANCH)
/* 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