/*
* Intel 7300 class Memory Controllers kernel module (Clarksboro)
*
* This file may be distributed under the terms of the
* GNU General Public License version 2 only.
*
* Copyright (c) 2010 by:
* Mauro Carvalho Chehab <mchehab@redhat.com>
*
* Red Hat Inc. http://www.redhat.com
*
* Intel 7300 Chipset Memory Controller Hub (MCH) - Datasheet
* http://www.intel.com/Assets/PDF/datasheet/318082.pdf
*
* TODO: The chipset allow checking for PCI Express errors also. Currently,
* the driver covers only memory error errors
*
* This driver uses "csrows" EDAC attribute to represent DIMM slot#
*/
#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 I7300 module when modifications are made
*/
#define I7300_REVISION " Ver: 1.0.0 " __DATE__
#define EDAC_MOD_STR "i7300_edac"
#define i7300_printk(level, fmt, arg...) \
edac_printk(level, "i7300", fmt, ##arg)
#define i7300_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "i7300", fmt, ##arg)
/*
* Memory topology is organized as:
* Branch 0 - 2 channels: channels 0 and 1 (FDB0 PCI dev 21.0)
* Branch 1 - 2 channels: channels 2 and 3 (FDB1 PCI dev 22.0)
* Each channel can have to 8 DIMM sets (called as SLOTS)
* Slots should generally be filled in pairs
* Except on Single Channel mode of operation
* just slot 0/channel0 filled on this mode
* On normal operation mode, the two channels on a branch should be
* filled together for the same SLOT#
* When in mirrored mode, Branch 1 replicate memory at Branch 0, so, the four
* channels on both branches should be filled
*/
/* Limits for i7300 */
#define MAX_SLOTS 8
#define MAX_BRANCHES 2
#define MAX_CH_PER_BRANCH 2
#define MAX_CHANNELS (MAX_CH_PER_BRANCH * MAX_BRANCHES)
#define MAX_MIR 3
#define to_channel(ch, branch) ((((branch)) << 1) | (ch))
#define to_csrow(slot, ch, branch) \
(to_channel(ch, branch) | ((slot) << 2))
/*
* I7300 devices
* All 3 functions of Device 16 (0,1,2) share the SAME DID and
* uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2),
* PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1
* for device 21 (0,1).
*/
/****************************************************
* i7300 Register definitions for memory enumberation
****************************************************/
/*
* Device 16,
* Function 0: System Address (not documented)
* Function 1: Memory Branch Map, Control, Errors Register
*/
/* 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 MC_SETTINGS 0x40
#define TOLM 0x6C
#define REDMEMB 0x7C
#define MIR0 0x80
#define MIR1 0x84
#define MIR2 0x88
/*
* Note: Other Intel EDAC drivers use AMBPRESENT to identify if the available
* memory. From datasheet item 7.3.1 (FB-DIMM technology & organization), it
* seems that we cannot use this information directly for the same usage.
* Each memory slot may have up to 2 AMB interfaces, one for income and another
* for outcome interface to the next slot.
* For now, the driver just stores the AMB present registers, but rely only at
* the MTR info to detect memory.
* Datasheet is also not clear about how to map each AMBPRESENT registers to
* one of the 4 available channels.
*/
#define AMBPRESENT_0 0x64
#define AMBPRESENT_1 0x66
const static u16 mtr_regs [MAX_SLOTS] = {
0x80, 0x84, 0x88, 0x8c,
0x82, 0x86, 0x8a, 0x8e
};
/* Defines to extract the vaious fields from the
* MTRx - Memory Technology Registers
*/
#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 8))
#define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 7))
#define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 6)) ? 8 : 4)
#define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 5)) ? 8 : 4)
#define MTR_DIMM_RANKS(mtr) (((mtr) & (1 << 4)) ? 1 : 0)
#define MTR_DIMM_ROWS(mtr)