1fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab/* 2fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Intel 7300 class Memory Controllers kernel module (Clarksboro) 3fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 4fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * This file may be distributed under the terms of the 5fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * GNU General Public License version 2 only. 6fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 7fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Copyright (c) 2010 by: 837e59f876bc710d67a30b660826a5e83e07101ceMauro Carvalho Chehab * Mauro Carvalho Chehab 9fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 10fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Red Hat Inc. http://www.redhat.com 11fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 12fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Intel 7300 Chipset Memory Controller Hub (MCH) - Datasheet 13fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * http://www.intel.com/Assets/PDF/datasheet/318082.pdf 14fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 15fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * TODO: The chipset allow checking for PCI Express errors also. Currently, 16fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * the driver covers only memory error errors 17fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 18fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * This driver uses "csrows" EDAC attribute to represent DIMM slot# 19fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 20fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 21fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include <linux/module.h> 22fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include <linux/init.h> 23fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include <linux/pci.h> 24fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include <linux/pci_ids.h> 25fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include <linux/slab.h> 26fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include <linux/edac.h> 27fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include <linux/mmzone.h> 28fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 29fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#include "edac_core.h" 30fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 31fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab/* 32fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Alter this version for the I7300 module when modifications are made 33fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 34152ba3942276c2a240703669ae4a3099e0a79451Michal Marek#define I7300_REVISION " Ver: 1.0.0" 35fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 36fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define EDAC_MOD_STR "i7300_edac" 37fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 38fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define i7300_printk(level, fmt, arg...) \ 39fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab edac_printk(level, "i7300", fmt, ##arg) 40fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 41fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define i7300_mc_printk(mci, level, fmt, arg...) \ 42fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab edac_mc_chipset_printk(mci, level, "i7300", fmt, ##arg) 43fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 44b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab/*********************************************** 45b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab * i7300 Limit constants Structs and static vars 46b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab ***********************************************/ 47b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 48fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab/* 49fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Memory topology is organized as: 50fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Branch 0 - 2 channels: channels 0 and 1 (FDB0 PCI dev 21.0) 51fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Branch 1 - 2 channels: channels 2 and 3 (FDB1 PCI dev 22.0) 52fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Each channel can have to 8 DIMM sets (called as SLOTS) 53fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Slots should generally be filled in pairs 54fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Except on Single Channel mode of operation 55fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * just slot 0/channel0 filled on this mode 56fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * On normal operation mode, the two channels on a branch should be 57c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab * filled together for the same SLOT# 58fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * When in mirrored mode, Branch 1 replicate memory at Branch 0, so, the four 59fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * channels on both branches should be filled 60fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 61fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 62fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab/* Limits for i7300 */ 63fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MAX_SLOTS 8 64fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MAX_BRANCHES 2 65fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MAX_CH_PER_BRANCH 2 66fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MAX_CHANNELS (MAX_CH_PER_BRANCH * MAX_BRANCHES) 67fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MAX_MIR 3 68fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 69fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define to_channel(ch, branch) ((((branch)) << 1) | (ch)) 70fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 71fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define to_csrow(slot, ch, branch) \ 72fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab (to_channel(ch, branch) | ((slot) << 2)) 73fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 74b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab/* Device name and register DID (Device ID) */ 75b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehabstruct i7300_dev_info { 76b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab const char *ctl_name; /* name for this device */ 77b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab u16 fsb_mapping_errors; /* DID for the branchmap,control */ 78b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab}; 79b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 80b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab/* Table of devices attributes supported by this driver */ 81b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehabstatic const struct i7300_dev_info i7300_devs[] = { 82b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab { 83b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab .ctl_name = "I7300", 84b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, 85b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab }, 86b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab}; 87b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 88b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehabstruct i7300_dimm_info { 89b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab int megabytes; /* size, 0 means not present */ 90b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab}; 91b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 92b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab/* driver private data structure */ 93b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehabstruct i7300_pvt { 94b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab struct pci_dev *pci_dev_16_0_fsb_ctlr; /* 16.0 */ 95b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab struct pci_dev *pci_dev_16_1_fsb_addr_map; /* 16.1 */ 96b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab struct pci_dev *pci_dev_16_2_fsb_err_regs; /* 16.2 */ 97b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab struct pci_dev *pci_dev_2x_0_fbd_branch[MAX_BRANCHES]; /* 21.0 and 22.0 */ 98b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 99b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab u16 tolm; /* top of low memory */ 100b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab u64 ambase; /* AMB BAR */ 101b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 102b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab u32 mc_settings; /* Report several settings */ 103b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab u32 mc_settings_a; 104b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 105b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab u16 mir[MAX_MIR]; /* Memory Interleave Reg*/ 106b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 1079c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */ 108b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab u16 ambpresent[MAX_CHANNELS]; /* AMB present regs */ 109b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 110b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab /* DIMM information matrix, allocating architecture maximums */ 111b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab struct i7300_dimm_info dimm_info[MAX_SLOTS][MAX_CHANNELS]; 112b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 113b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab /* Temporary buffer for use when preparing error messages */ 114b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab char *tmp_prt_buffer; 115b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab}; 116b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 117b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab/* FIXME: Why do we need to have this static? */ 118b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehabstatic struct edac_pci_ctl_info *i7300_pci; 119b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 120b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab/*************************************************** 121b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab * i7300 Register definitions for memory enumeration 122b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab ***************************************************/ 123b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab 124c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab/* 125c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab * Device 16, 126c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab * Function 0: System Address (not documented) 127c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab * Function 1: Memory Branch Map, Control, Errors Register 128c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab */ 129c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab 130fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* OFFSETS for Function 0 */ 131af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */ 132af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define MAXCH 0x56 /* Max Channel Number */ 133af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */ 134fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 135fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* OFFSETS for Function 1 */ 136af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define MC_SETTINGS 0x40 137bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab #define IS_MIRRORED(mc) ((mc) & (1 << 16)) 138bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab #define IS_ECC_ENABLED(mc) ((mc) & (1 << 5)) 139bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab #define IS_RETRY_ENABLED(mc) ((mc) & (1 << 31)) 140bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab #define IS_SCRBALGO_ENHANCED(mc) ((mc) & (1 << 8)) 141fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 142bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab#define MC_SETTINGS_A 0x58 143bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab #define IS_SINGLE_MODE(mca) ((mca) & (1 << 14)) 144d7de2bdb0e15c594aefbc71d899c4684a5ce6559Mauro Carvalho Chehab 145af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define TOLM 0x6C 146af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab 147af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define MIR0 0x80 148af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define MIR1 0x84 149af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab#define MIR2 0x88 150fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 151fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab/* 152fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Note: Other Intel EDAC drivers use AMBPRESENT to identify if the available 153fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * memory. From datasheet item 7.3.1 (FB-DIMM technology & organization), it 154fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * seems that we cannot use this information directly for the same usage. 155fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Each memory slot may have up to 2 AMB interfaces, one for income and another 156fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * for outcome interface to the next slot. 157fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * For now, the driver just stores the AMB present registers, but rely only at 158fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * the MTR info to detect memory. 159fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * Datasheet is also not clear about how to map each AMBPRESENT registers to 160fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * one of the 4 available channels. 161fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 162fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define AMBPRESENT_0 0x64 163fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define AMBPRESENT_1 0x66 164fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 16542b16b3fbb5ee4555f5dee6220f3ccaa6e1ebe47Jesper Juhlstatic const u16 mtr_regs[MAX_SLOTS] = { 166fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 0x80, 0x84, 0x88, 0x8c, 167fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 0x82, 0x86, 0x8a, 0x8e 168fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab}; 169fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 170b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab/* 171b4552aceb37ef953db14b9851bd4ededabc3c77bMauro Carvalho Chehab * Defines to extract the vaious fields from the 172fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * MTRx - Memory Technology Registers 173fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 174fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 8)) 175fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 7)) 176fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 6)) ? 8 : 4) 177fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 5)) ? 8 : 4) 178fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DIMM_RANKS(mtr) (((mtr) & (1 << 4)) ? 1 : 0) 179fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3) 180fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DRAM_BANKS_ADDR_BITS 2 181fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13) 182fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) 183fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab#define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) 184fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 185c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab/************************************************ 186c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab * i7300 Register definitions for error detection 187c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab ************************************************/ 18857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 18957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab/* 19057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab * Device 16.1: FBD Error Registers 19157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab */ 19257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab#define FERR_FAT_FBD 0x98 19357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehabstatic const char *ferr_fat_fbd_name[] = { 19457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [22] = "Non-Redundant Fast Reset Timeout", 19557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [2] = ">Tmid Thermal event with intelligent throttling disabled", 19657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [1] = "Memory or FBD configuration CRC read error", 19757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [0] = "Memory Write error on non-redundant retry or " 19857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab "FBD configuration Write error on retry", 19957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab}; 2007e06b7a3333f5c7a0cec12aff20d39c5c87c0795Jean Delvare#define GET_FBD_FAT_IDX(fbderr) (((fbderr) >> 28) & 3) 2017e06b7a3333f5c7a0cec12aff20d39c5c87c0795Jean Delvare#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22)) 20257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 20357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab#define FERR_NF_FBD 0xa0 20457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehabstatic const char *ferr_nf_fbd_name[] = { 20557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [24] = "DIMM-Spare Copy Completed", 20657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [23] = "DIMM-Spare Copy Initiated", 20757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [22] = "Redundant Fast Reset Timeout", 20857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [21] = "Memory Write error on redundant retry", 20957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [18] = "SPD protocol Error", 21057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [17] = "FBD Northbound parity error on FBD Sync Status", 21157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [16] = "Correctable Patrol Data ECC", 21257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [15] = "Correctable Resilver- or Spare-Copy Data ECC", 21357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [14] = "Correctable Mirrored Demand Data ECC", 21457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [13] = "Correctable Non-Mirrored Demand Data ECC", 21557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [11] = "Memory or FBD configuration CRC read error", 21657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [10] = "FBD Configuration Write error on first attempt", 21757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [9] = "Memory Write error on first attempt", 21857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [8] = "Non-Aliased Uncorrectable Patrol Data ECC", 21957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [7] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", 22057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [6] = "Non-Aliased Uncorrectable Mirrored Demand Data ECC", 22157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [5] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC", 22257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [4] = "Aliased Uncorrectable Patrol Data ECC", 22357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [3] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", 22457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [2] = "Aliased Uncorrectable Mirrored Demand Data ECC", 22557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", 22657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab [0] = "Uncorrectable Data ECC on Replay", 22757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab}; 2287e06b7a3333f5c7a0cec12aff20d39c5c87c0795Jean Delvare#define GET_FBD_NF_IDX(fbderr) (((fbderr) >> 28) & 3) 22957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab#define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\ 23057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\ 23157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\ 23257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\ 23357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\ 23457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 1) | (1 << 0)) 23557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 23657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab#define EMASK_FBD 0xa8 23757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab#define EMASK_FBD_ERR_MASK ((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24) |\ 23857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 22) | (1 << 21) | (1 << 20) | (1 << 19) |\ 23957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 18) | (1 << 17) | (1 << 16) | (1 << 14) |\ 24057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 13) | (1 << 12) | (1 << 11) | (1 << 10) |\ 24157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\ 24257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\ 24357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab (1 << 1) | (1 << 0)) 24457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 245c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab/* 246c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab * Device 16.2: Global Error Registers 247c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab */ 248c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab 2495de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab#define FERR_GLOBAL_HI 0x48 2505de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehabstatic const char *ferr_global_hi_name[] = { 2515de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab [3] = "FSB 3 Fatal Error", 2525de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab [2] = "FSB 2 Fatal Error", 2535de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab [1] = "FSB 1 Fatal Error", 2545de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab [0] = "FSB 0 Fatal Error", 2555de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab}; 2565de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab#define ferr_global_hi_is_fatal(errno) 1 2575de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab 258c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab#define FERR_GLOBAL_LO 0x40 2595de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehabstatic const char *ferr_global_lo_name[] = { 260c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [31] = "Internal MCH Fatal Error", 261c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [30] = "Intel QuickData Technology Device Fatal Error", 262c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [29] = "FSB1 Fatal Error", 263c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [28] = "FSB0 Fatal Error", 264c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [27] = "FBD Channel 3 Fatal Error", 265c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [26] = "FBD Channel 2 Fatal Error", 266c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [25] = "FBD Channel 1 Fatal Error", 267c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [24] = "FBD Channel 0 Fatal Error", 268c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [23] = "PCI Express Device 7Fatal Error", 269c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [22] = "PCI Express Device 6 Fatal Error", 270c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [21] = "PCI Express Device 5 Fatal Error", 271c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [20] = "PCI Express Device 4 Fatal Error", 272c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [19] = "PCI Express Device 3 Fatal Error", 273c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [18] = "PCI Express Device 2 Fatal Error", 274c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [17] = "PCI Express Device 1 Fatal Error", 275c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [16] = "ESI Fatal Error", 276c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [15] = "Internal MCH Non-Fatal Error", 277c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [14] = "Intel QuickData Technology Device Non Fatal Error", 278c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [13] = "FSB1 Non-Fatal Error", 279c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [12] = "FSB 0 Non-Fatal Error", 280c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [11] = "FBD Channel 3 Non-Fatal Error", 281c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [10] = "FBD Channel 2 Non-Fatal Error", 282c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [9] = "FBD Channel 1 Non-Fatal Error", 283c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [8] = "FBD Channel 0 Non-Fatal Error", 284c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [7] = "PCI Express Device 7 Non-Fatal Error", 285c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [6] = "PCI Express Device 6 Non-Fatal Error", 286c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [5] = "PCI Express Device 5 Non-Fatal Error", 287c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [4] = "PCI Express Device 4 Non-Fatal Error", 288c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [3] = "PCI Express Device 3 Non-Fatal Error", 289c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [2] = "PCI Express Device 2 Non-Fatal Error", 290c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [1] = "PCI Express Device 1 Non-Fatal Error", 291c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab [0] = "ESI Non-Fatal Error", 292c3af2eaf7a3257f7b44165ec487215574c47fd32Mauro Carvalho Chehab}; 2935de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab#define ferr_global_lo_is_fatal(errno) ((errno < 16) ? 0 : 1) 294fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 2958199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab#define NRECMEMA 0xbe 2968199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab #define NRECMEMA_BANK(v) (((v) >> 12) & 7) 2978199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab #define NRECMEMA_RANK(v) (((v) >> 8) & 15) 2988199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab 2998199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab#define NRECMEMB 0xc0 3008199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab #define NRECMEMB_IS_WR(v) ((v) & (1 << 31)) 3018199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab #define NRECMEMB_CAS(v) (((v) >> 16) & 0x1fff) 3028199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab #define NRECMEMB_RAS(v) ((v) & 0xffff) 3038199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab 30432f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab#define REDMEMA 0xdc 30532f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab 30637b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab#define REDMEMB 0x7c 30737b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab #define IS_SECOND_CH(v) ((v) * (1 << 17)) 30837b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab 30932f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab#define RECMEMA 0xe0 31032f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab #define RECMEMA_BANK(v) (((v) >> 12) & 7) 31132f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab #define RECMEMA_RANK(v) (((v) >> 8) & 15) 31232f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab 31332f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab#define RECMEMB 0xe4 31432f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab #define RECMEMB_IS_WR(v) ((v) & (1 << 31)) 31532f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab #define RECMEMB_CAS(v) (((v) >> 16) & 0x1fff) 31632f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab #define RECMEMB_RAS(v) ((v) & 0xffff) 31732f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab 3185de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab/******************************************** 3195de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab * i7300 Functions related to error detection 3205de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab ********************************************/ 321fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 322d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 323d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * get_err_from_table() - Gets the error message from a table 324d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @table: table name (array of char *) 325d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @size: number of elements at the table 326d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @pos: position of the element to be returned 327d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * 328d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * This is a small routine that gets the pos-th element of a table. If the 329d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * element doesn't exist (or it is empty), it returns "reserved". 330d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Instead of calling it directly, the better is to call via the macro 331d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * GET_ERR_FROM_TABLE(), that automatically checks the table size via 332d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * ARRAY_SIZE() macro 333d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab */ 334d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehabstatic const char *get_err_from_table(const char *table[], int size, int pos) 335fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 336d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab if (unlikely(pos >= size)) 337d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab return "Reserved"; 338d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab 339d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab if (unlikely(!table[pos])) 3405de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab return "Reserved"; 3415de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab 3425de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab return table[pos]; 343fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 344fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 3455de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab#define GET_ERR_FROM_TABLE(table, pos) \ 3465de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab get_err_from_table(table, ARRAY_SIZE(table), pos) 3475de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab 348d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 349d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_process_error_global() - Retrieve the hardware error information from 350d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * the hardware global error registers and 351d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * sends it to dmesg 352d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 353fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 354f42774224860d7c3f7c06559f98b681197999f9eMauro Carvalho Chehabstatic void i7300_process_error_global(struct mem_ctl_info *mci) 355fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 3565de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab struct i7300_pvt *pvt; 3575f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab u32 errnum, error_reg; 3585de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab unsigned long errors; 3595de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab const char *specific; 3605de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab bool is_fatal; 361fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 3625de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab pvt = mci->pvt_info; 363fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 3645de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab /* read in the 1st FATAL error register */ 3655de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 3665f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_GLOBAL_HI, &error_reg); 3675f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab if (unlikely(error_reg)) { 3685f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab errors = error_reg; 3695de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab errnum = find_first_bit(&errors, 3705de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab ARRAY_SIZE(ferr_global_hi_name)); 3715de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum); 3725de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab is_fatal = ferr_global_hi_is_fatal(errnum); 37386002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab 37486002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab /* Clear the error bit */ 37586002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 3765f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_GLOBAL_HI, error_reg); 37786002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab 3785de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab goto error_global; 379fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 380fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 3815de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 3825f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_GLOBAL_LO, &error_reg); 3835f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab if (unlikely(error_reg)) { 3845f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab errors = error_reg; 3855de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab errnum = find_first_bit(&errors, 3865de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab ARRAY_SIZE(ferr_global_lo_name)); 3875de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum); 3885de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab is_fatal = ferr_global_lo_is_fatal(errnum); 38986002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab 39086002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab /* Clear the error bit */ 39186002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 3925f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_GLOBAL_LO, error_reg); 39386002324cf8809c72858741ab20bb7a855654b4cMauro Carvalho Chehab 3945de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab goto error_global; 3955de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab } 3965de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab return; 397fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 3985de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehaberror_global: 3995de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab i7300_mc_printk(mci, KERN_EMERG, "%s misc error: %s\n", 4005de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab is_fatal ? "Fatal" : "NOT fatal", specific); 401fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 402fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 403d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 404d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_process_fbd_error() - Retrieve the hardware error information from 405d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * the FBD error registers and sends it via 406d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * EDAC error API calls 407d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 40857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab */ 409f42774224860d7c3f7c06559f98b681197999f9eMauro Carvalho Chehabstatic void i7300_process_fbd_error(struct mem_ctl_info *mci) 41057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab{ 41157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab struct i7300_pvt *pvt; 4125f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab u32 errnum, value, error_reg; 4138199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab u16 val16; 41437b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab unsigned branch, channel, bank, rank, cas, ras; 41532f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab u32 syndrome; 41632f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab 41757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab unsigned long errors; 41857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab const char *specific; 41932f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab bool is_wr; 42057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 42157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab pvt = mci->pvt_info; 42257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 42357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab /* read in the 1st FATAL error register */ 42457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 4255f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_FAT_FBD, &error_reg); 4265f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab if (unlikely(error_reg & FERR_FAT_FBD_ERR_MASK)) { 4275f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab errors = error_reg & FERR_FAT_FBD_ERR_MASK ; 42857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab errnum = find_first_bit(&errors, 42957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab ARRAY_SIZE(ferr_fat_fbd_name)); 43057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum); 4315f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0; 43257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 4338199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, 4348199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab NRECMEMA, &val16); 4358199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab bank = NRECMEMA_BANK(val16); 4368199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab rank = NRECMEMA_RANK(val16); 4378199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab 4388199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 4398199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab NRECMEMB, &value); 4408199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab is_wr = NRECMEMB_IS_WR(value); 4418199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab cas = NRECMEMB_CAS(value); 4428199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab ras = NRECMEMB_RAS(value); 4438199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab 4445f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab /* Clean the error register */ 4455f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 4465f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_FAT_FBD, error_reg); 4475f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab 4488199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, 44970e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab "Bank=%d RAS=%d CAS=%d Err=0x%lx (%s))", 45070e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab bank, ras, cas, errors, specific); 45170e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab 4529eb07a7fb8a90ee39fa9d5489afc0330cfcfbea7Mauro Carvalho Chehab edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0, 45370e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab branch, -1, rank, 45470e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab is_wr ? "Write error" : "Read error", 45503f7eae80f4b913929be84e0c883ee98196fd6ffMauro Carvalho Chehab pvt->tmp_prt_buffer); 45670e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab 45757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab } 45857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 45957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab /* read in the 1st NON-FATAL error register */ 46057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 4615f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_NF_FBD, &error_reg); 4625f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab if (unlikely(error_reg & FERR_NF_FBD_ERR_MASK)) { 4635f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab errors = error_reg & FERR_NF_FBD_ERR_MASK; 46457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab errnum = find_first_bit(&errors, 46557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab ARRAY_SIZE(ferr_nf_fbd_name)); 46657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); 4677e06b7a3333f5c7a0cec12aff20d39c5c87c0795Jean Delvare branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0; 46857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 46932f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 47032f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab REDMEMA, &syndrome); 47132f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab 47232f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, 47332f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab RECMEMA, &val16); 47432f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab bank = RECMEMA_BANK(val16); 47532f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab rank = RECMEMA_RANK(val16); 47632f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab 47732f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 47832f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab RECMEMB, &value); 47932f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab is_wr = RECMEMB_IS_WR(value); 48032f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab cas = RECMEMB_CAS(value); 48132f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab ras = RECMEMB_RAS(value); 4828199d8cc65787bfd83abbfb69d9de1b51e027c41Mauro Carvalho Chehab 48337b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 48437b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab REDMEMB, &value); 48537b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab channel = (branch << 1); 48637b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab if (IS_SECOND_CH(value)) 48737b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab channel++; 48837b69cf91c2c6e60856ad1ac4c37ccb2005ebbd3Mauro Carvalho Chehab 4895f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab /* Clear the error bit */ 4905f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 4915f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab FERR_NF_FBD, error_reg); 4925f032119d6f1cc48d0d1a28b8014f270ca4c4e47Mauro Carvalho Chehab 49332f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab /* Form out message */ 49432f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, 49570e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab "DRAM-Bank=%d RAS=%d CAS=%d, Err=0x%lx (%s))", 49670e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab bank, ras, cas, errors, specific); 49770e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab 4989eb07a7fb8a90ee39fa9d5489afc0330cfcfbea7Mauro Carvalho Chehab edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 49970e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab syndrome, 50070e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab branch >> 1, channel % 2, rank, 50170e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab is_wr ? "Write error" : "Read error", 50203f7eae80f4b913929be84e0c883ee98196fd6ffMauro Carvalho Chehab pvt->tmp_prt_buffer); 50332f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab } 50432f9472613b30791d8cb5a953791cf4647166744Mauro Carvalho Chehab return; 50557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab} 50657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 507d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 508d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_check_error() - Calls the error checking subroutines 509d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 510fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 511f42774224860d7c3f7c06559f98b681197999f9eMauro Carvalho Chehabstatic void i7300_check_error(struct mem_ctl_info *mci) 5125de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab{ 513f42774224860d7c3f7c06559f98b681197999f9eMauro Carvalho Chehab i7300_process_error_global(mci); 514f42774224860d7c3f7c06559f98b681197999f9eMauro Carvalho Chehab i7300_process_fbd_error(mci); 5155de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab}; 516fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 517d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 518d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_clear_error() - Clears the error registers 519d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 520fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 521fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic void i7300_clear_error(struct mem_ctl_info *mci) 522fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 523e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab struct i7300_pvt *pvt = mci->pvt_info; 524e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab u32 value; 525e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab /* 526e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab * All error values are RWC - we need to read and write 1 to the 527e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab * bit that we want to cleanup 528e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab */ 529fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 530e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab /* Clear global error registers */ 531e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 532e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_GLOBAL_HI, &value); 533e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 534e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_GLOBAL_HI, value); 535e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab 536e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 537e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_GLOBAL_LO, &value); 538e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, 539e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_GLOBAL_LO, value); 540e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab 541e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab /* Clear FBD error registers */ 542e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 543e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_FAT_FBD, &value); 544e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 545e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_FAT_FBD, value); 546e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab 547e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 548e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_NF_FBD, &value); 549e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 550e43276050927c7dfc45b1e2f090b94f72f87c052Mauro Carvalho Chehab FERR_NF_FBD, value); 551fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 552fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 553d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 554d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_enable_error_reporting() - Enable the memory reporting logic at the 555d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * hardware 556d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 557fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 558fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic void i7300_enable_error_reporting(struct mem_ctl_info *mci) 559fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 56057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab struct i7300_pvt *pvt = mci->pvt_info; 56157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab u32 fbd_error_mask; 56257021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 56357021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab /* Read the FBD Error Mask Register */ 56457021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 56557021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab EMASK_FBD, &fbd_error_mask); 56657021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 56757021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab /* Enable with a '0' */ 56857021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab fbd_error_mask &= ~(EMASK_FBD_ERR_MASK); 56957021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab 57057021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, 57157021918aa9c310524d7e9754506e4e8272b4c0eMauro Carvalho Chehab EMASK_FBD, fbd_error_mask); 572fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 5735de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab 5745de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab/************************************************ 5755de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab * i7300 Functions related to memory enumberation 5765de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab ************************************************/ 577fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 578d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 579d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * decode_mtr() - Decodes the MTR descriptor, filling the edac structs 580d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @pvt: pointer to the private data struct used by i7300 driver 581d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @slot: DIMM slot (0 to 7) 582d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @ch: Channel number within the branch (0 or 1) 583d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @branch: Branch number (0 or 1) 584d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @dinfo: Pointer to DIMM info where dimm size is stored 585d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @p_csrow: Pointer to the struct csrow_info that corresponds to that element 586fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 587fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic int decode_mtr(struct i7300_pvt *pvt, 588fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int slot, int ch, int branch, 589fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_dimm_info *dinfo, 590a895bf8b1e1ea4c032a8fa8a09475a2ce09fe77aMauro Carvalho Chehab struct dimm_info *dimm) 591fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 592fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int mtr, ans, addrBits, channel; 593fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 594fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab channel = to_channel(ch, branch); 595fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 596fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mtr = pvt->mtr[slot][branch]; 597fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab ans = MTR_DIMMS_PRESENT(mtr) ? 1 : 0; 598fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 599956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\tMTR%d CH%d: DIMMs are %sPresent (mtr)\n", 600956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches slot, channel, ans ? "" : "NOT "); 601fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 602fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Determine if there is a DIMM present in this DIMM slot */ 603fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (!ans) 604fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return 0; 605fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 606fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Start with the number of bits for a Bank 607fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * on the DRAM */ 608fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab addrBits = MTR_DRAM_BANKS_ADDR_BITS; 609fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Add thenumber of ROW bits */ 610fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr); 611fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* add the number of COLUMN bits */ 612fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); 613fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* add the number of RANK bits */ 614fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab addrBits += MTR_DIMM_RANKS(mtr); 615fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 616fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab addrBits += 6; /* add 64 bits per DIMM */ 617fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab addrBits -= 20; /* divide by 2^^20 */ 618fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab addrBits -= 3; /* 8 bits per bytes */ 619fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 620fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab dinfo->megabytes = 1 << addrBits; 621fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 622956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); 623956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches 624956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tELECTRICAL THROTTLING is %s\n", 625956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); 626956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches 627956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); 628956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tNUMRANK: %s\n", 629956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMM_RANKS(mtr) ? "double" : "single"); 630956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tNUMROW: %s\n", 631956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : 632956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : 633956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : 634956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches "65,536 - 16 rows"); 635956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tNUMCOL: %s\n", 636956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : 637956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : 638956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : 639956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches "reserved"); 640956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tSIZE: %d MB\n", dinfo->megabytes); 641fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 642116389ed21e4ad88f65e7ec5ed6ca224acb89115Mauro Carvalho Chehab /* 64315154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab * The type of error detection actually depends of the 644116389ed21e4ad88f65e7ec5ed6ca224acb89115Mauro Carvalho Chehab * mode of operation. When it is just one single memory chip, at 64515154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab * socket 0, channel 0, it uses 8-byte-over-32-byte SECDED+ code. 64615154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab * In normal or mirrored mode, it uses Lockstep mode, 647116389ed21e4ad88f65e7ec5ed6ca224acb89115Mauro Carvalho Chehab * with the possibility of using an extended algorithm for x8 memories 648116389ed21e4ad88f65e7ec5ed6ca224acb89115Mauro Carvalho Chehab * See datasheet Sections 7.3.6 to 7.3.8 649116389ed21e4ad88f65e7ec5ed6ca224acb89115Mauro Carvalho Chehab */ 65015154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab 651a895bf8b1e1ea4c032a8fa8a09475a2ce09fe77aMauro Carvalho Chehab dimm->nr_pages = MiB_TO_PAGES(dinfo->megabytes); 652084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab dimm->grain = 8; 653084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab dimm->mtype = MEM_FB_DDR2; 65415154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab if (IS_SINGLE_MODE(pvt->mc_settings_a)) { 655084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab dimm->edac_mode = EDAC_SECDED; 656956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); 65715154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab } else { 658956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tECC code is on Lockstep mode\n"); 65928c2ce7c8b275a8e6950bacb2dbad70b36a2996bMauro Carvalho Chehab if (MTR_DRAM_WIDTH(mtr) == 8) 660084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab dimm->edac_mode = EDAC_S8ECD8ED; 66115154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab else 662084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab dimm->edac_mode = EDAC_S4ECD4ED; 66315154c57c62494292f43df9133a7b370cbbf1ecbMauro Carvalho Chehab } 664fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 665fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* ask what device type on this row */ 66628c2ce7c8b275a8e6950bacb2dbad70b36a2996bMauro Carvalho Chehab if (MTR_DRAM_WIDTH(mtr) == 8) { 667956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tScrub algorithm for x8 is on %s mode\n", 668956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? 669956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches "enhanced" : "normal"); 670d7de2bdb0e15c594aefbc71d899c4684a5ce6559Mauro Carvalho Chehab 671084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab dimm->dtype = DEV_X8; 672d7de2bdb0e15c594aefbc71d899c4684a5ce6559Mauro Carvalho Chehab } else 673084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab dimm->dtype = DEV_X4; 674fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 675fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return mtr; 676fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 677fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 678d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 679d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * print_dimm_size() - Prints dump of the memory organization 680d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @pvt: pointer to the private data struct used by i7300 driver 681fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 682d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Useful for debug. If debug is disabled, this routine do nothing 683fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 684fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic void print_dimm_size(struct i7300_pvt *pvt) 685fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 686d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab#ifdef CONFIG_EDAC_DEBUG 687fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_dimm_info *dinfo; 68885580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab char *p; 689fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int space, n; 690fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int channel, slot; 691fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 692fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space = PAGE_SIZE; 69385580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab p = pvt->tmp_prt_buffer; 694fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 695fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab n = snprintf(p, space, " "); 696fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab p += n; 697fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space -= n; 698fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab for (channel = 0; channel < MAX_CHANNELS; channel++) { 699fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab n = snprintf(p, space, "channel %d | ", channel); 700fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab p += n; 701fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space -= n; 702fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 703956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); 70485580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab p = pvt->tmp_prt_buffer; 705fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space = PAGE_SIZE; 706fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab n = snprintf(p, space, "-------------------------------" 7079c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab "------------------------------"); 708fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab p += n; 709fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space -= n; 710956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); 71185580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab p = pvt->tmp_prt_buffer; 712fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space = PAGE_SIZE; 713fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 714fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab for (slot = 0; slot < MAX_SLOTS; slot++) { 715fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab n = snprintf(p, space, "csrow/SLOT %d ", slot); 716fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab p += n; 717fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space -= n; 718fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 719fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab for (channel = 0; channel < MAX_CHANNELS; channel++) { 720fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab dinfo = &pvt->dimm_info[slot][channel]; 721fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab n = snprintf(p, space, "%4d MB | ", dinfo->megabytes); 722fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab p += n; 723fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space -= n; 724fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 725fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 726956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); 72785580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab p = pvt->tmp_prt_buffer; 728fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space = PAGE_SIZE; 729fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 730fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 731fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab n = snprintf(p, space, "-------------------------------" 7329c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab "------------------------------"); 733fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab p += n; 734fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space -= n; 735956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); 73685580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab p = pvt->tmp_prt_buffer; 737fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab space = PAGE_SIZE; 738d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab#endif 739fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 740fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 741d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 742d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_init_csrows() - Initialize the 'csrows' table within 743d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * the mci control structure with the 744d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * addressing of memory. 745d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 746fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 747fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic int i7300_init_csrows(struct mem_ctl_info *mci) 748fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 749fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_pvt *pvt; 750fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_dimm_info *dinfo; 751d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab int rc = -ENODEV; 752fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int mtr; 75333ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab int ch, branch, slot, channel, max_channel, max_branch; 754084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab struct dimm_info *dimm; 755fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 756fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pvt = mci->pvt_info; 757fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 758956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "Memory Technology Registers:\n"); 759fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 76033ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab if (IS_SINGLE_MODE(pvt->mc_settings_a)) { 76133ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab max_branch = 1; 76233ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab max_channel = 1; 76333ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab } else { 76433ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab max_branch = MAX_BRANCHES; 76533ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab max_channel = MAX_CH_PER_BRANCH; 76633ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab } 76733ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab 768fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Get the AMB present registers for the four channels */ 76933ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab for (branch = 0; branch < max_branch; branch++) { 770fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Read and dump branch 0's MTRs */ 771fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab channel = to_channel(0, branch); 7729c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], 7739c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab AMBPRESENT_0, 774fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab &pvt->ambpresent[channel]); 775956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", 776956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches channel, pvt->ambpresent[channel]); 777fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 77833ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab if (max_channel == 1) 77933ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab continue; 78033ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab 781fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab channel = to_channel(1, branch); 7829c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], 7839c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab AMBPRESENT_1, 784fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab &pvt->ambpresent[channel]); 785956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", 786956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches channel, pvt->ambpresent[channel]); 787fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 788fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 789fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Get the set of MTR[0-7] regs by each branch */ 790fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab for (slot = 0; slot < MAX_SLOTS; slot++) { 791fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int where = mtr_regs[slot]; 79233ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab for (branch = 0; branch < max_branch; branch++) { 7933e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], 794fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab where, 795fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab &pvt->mtr[slot][branch]); 79633ad41263da5df8ac55d4010a015063ff88712e8Mauro Carvalho Chehab for (ch = 0; ch < max_channel; ch++) { 797fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int channel = to_channel(ch, branch); 798fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 79970e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, 80070e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab mci->n_layers, branch, ch, slot); 801fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 80270e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab dinfo = &pvt->dimm_info[slot][channel]; 803084a4fccef39ac7abb039511f32380f28d0b67e6Mauro Carvalho Chehab 804fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mtr = decode_mtr(pvt, slot, ch, branch, 805a895bf8b1e1ea4c032a8fa8a09475a2ce09fe77aMauro Carvalho Chehab dinfo, dimm); 806a895bf8b1e1ea4c032a8fa8a09475a2ce09fe77aMauro Carvalho Chehab 807fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* if no DIMMS on this row, continue */ 808fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (!MTR_DIMMS_PRESENT(mtr)) 809fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab continue; 810fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 811d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab rc = 0; 812a895bf8b1e1ea4c032a8fa8a09475a2ce09fe77aMauro Carvalho Chehab 813fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 814fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 815fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 816fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 817d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab return rc; 818fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 819fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 820d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 821d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * decode_mir() - Decodes Memory Interleave Register (MIR) info 822d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @int mir_no: number of the MIR register to decode 823d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mir: array with the MIR data cached on the driver 824d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab */ 825fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic void decode_mir(int mir_no, u16 mir[MAX_MIR]) 826fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 827fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (mir[mir_no] & 3) 828956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n", 829956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches mir_no, 830956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches (mir[mir_no] >> 4) & 0xfff, 831956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches (mir[mir_no] & 1) ? "B0" : "", 832956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches (mir[mir_no] & 2) ? "B1" : ""); 833fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 834fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 835d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 836d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_get_mc_regs() - Get the contents of the MC enumeration registers 837d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 838fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 839d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Data read is cached internally for its usage when needed 840fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 841fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic int i7300_get_mc_regs(struct mem_ctl_info *mci) 842fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 843fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_pvt *pvt; 844fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab u32 actual_tolm; 845fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int i, rc; 846fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 847fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pvt = mci->pvt_info; 848fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 8493e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_0_fsb_ctlr, AMBASE, 850fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab (u32 *) &pvt->ambase); 851fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 852956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase); 853fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 854fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Get the Branch Map regs */ 8553e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, TOLM, &pvt->tolm); 856fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pvt->tolm >>= 12; 857956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n", 858956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pvt->tolm, pvt->tolm); 859fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 860fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28)); 861956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "Actual TOLM byte addr=%u.%03u GB (0x%x)\n", 862956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); 863fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 864af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab /* Get memory controller settings */ 8653e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS, 866af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab &pvt->mc_settings); 867bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS_A, 868bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab &pvt->mc_settings_a); 869d7de2bdb0e15c594aefbc71d899c4684a5ce6559Mauro Carvalho Chehab 870bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab if (IS_SINGLE_MODE(pvt->mc_settings_a)) 871956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "Memory controller operating on single mode\n"); 872bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab else 873956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "Memory controller operating on %smirrored mode\n", 874956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches IS_MIRRORED(pvt->mc_settings) ? "" : "non-"); 875bb81a21637f84e2192bf327575645a7843c70cdbMauro Carvalho Chehab 876956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "Error detection is %s\n", 877956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); 878956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "Retry is %s\n", 879956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); 880af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab 881af3d8831e7e2036cd453c852d206b892b19c8820Mauro Carvalho Chehab /* Get Memory Interleave Range registers */ 8829c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, 8839c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab &pvt->mir[0]); 8849c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR1, 8859c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab &pvt->mir[1]); 8869c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR2, 8879c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab &pvt->mir[2]); 888fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 889fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Decode the MIR regs */ 890fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab for (i = 0; i < MAX_MIR; i++) 891fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab decode_mir(i, pvt->mir); 892fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 893fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab rc = i7300_init_csrows(mci); 894fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (rc < 0) 895fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return rc; 896fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 897fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Go and determine the size of each DIMM and place in an 898fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * orderly matrix */ 899fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab print_dimm_size(pvt); 900fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 901fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return 0; 902fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 903fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 9045de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab/************************************************* 9055de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab * i7300 Functions related to device probe/release 9065de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab *************************************************/ 9075de6e07ed75ee29a302f50e149339ca747131121Mauro Carvalho Chehab 908d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 909d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_put_devices() - Release the PCI devices 910d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 911fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 912fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic void i7300_put_devices(struct mem_ctl_info *mci) 913fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 914fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_pvt *pvt; 915fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int branch; 916fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 917fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pvt = mci->pvt_info; 918fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 919fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Decrement usage count for devices */ 920fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab for (branch = 0; branch < MAX_CH_PER_BRANCH; branch++) 9213e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pci_dev_put(pvt->pci_dev_2x_0_fbd_branch[branch]); 9223e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pci_dev_put(pvt->pci_dev_16_2_fsb_err_regs); 9233e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pci_dev_put(pvt->pci_dev_16_1_fsb_addr_map); 924fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 925fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 926d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 927d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_get_devices() - Find and perform 'get' operation on the MCH's 928d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * device/functions we want to reference for this driver 929d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @mci: struct mem_ctl_info pointer 930fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 931d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Access and prepare the several devices for usage: 932d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * I7300 devices used by this driver: 933d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Device 16, functions 0,1 and 2: PCI_DEVICE_ID_INTEL_I7300_MCH_ERR 934d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Device 21 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 935d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Device 22 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 936fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 9379b3c6e85c2cfa731cf67d5a8c49f7d8c60ec0b04Greg Kroah-Hartmanstatic int i7300_get_devices(struct mem_ctl_info *mci) 938fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 939fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_pvt *pvt; 940fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct pci_dev *pdev; 941fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 942fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pvt = mci->pvt_info; 943fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 944fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Attempt to 'get' the MCH register we want */ 945fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pdev = NULL; 94675135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 94775135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, 94875135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare pdev))) { 949fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Store device 16 funcs 1 and 2 */ 950fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab switch (PCI_FUNC(pdev->devfn)) { 951fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab case 1: 95275135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare if (!pvt->pci_dev_16_1_fsb_addr_map) 95375135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare pvt->pci_dev_16_1_fsb_addr_map = 95475135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare pci_dev_get(pdev); 955fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab break; 956fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab case 2: 95775135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare if (!pvt->pci_dev_16_2_fsb_err_regs) 95875135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare pvt->pci_dev_16_2_fsb_err_regs = 95975135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare pci_dev_get(pdev); 960fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab break; 961fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 962fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 963fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 96475135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare if (!pvt->pci_dev_16_1_fsb_addr_map || 96575135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare !pvt->pci_dev_16_2_fsb_err_regs) { 96675135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare /* At least one device was not found */ 96775135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare i7300_printk(KERN_ERR, 96875135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare "'system address,Process Bus' device not found:" 96975135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare "vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n", 97075135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare PCI_VENDOR_ID_INTEL, 97175135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare PCI_DEVICE_ID_INTEL_I7300_MCH_ERR); 97275135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare goto error; 97375135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare } 97475135da0d68419ef8a925f4c1d5f63d8046e314dJean Delvare 975956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", 976956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pci_name(pvt->pci_dev_16_0_fsb_ctlr), 977956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pvt->pci_dev_16_0_fsb_ctlr->vendor, 978956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pvt->pci_dev_16_0_fsb_ctlr->device); 979956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", 980956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pci_name(pvt->pci_dev_16_1_fsb_addr_map), 981956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pvt->pci_dev_16_1_fsb_addr_map->vendor, 982956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pvt->pci_dev_16_1_fsb_addr_map->device); 983956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n", 984956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pci_name(pvt->pci_dev_16_2_fsb_err_regs), 985956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pvt->pci_dev_16_2_fsb_err_regs->vendor, 986956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pvt->pci_dev_16_2_fsb_err_regs->device); 987fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 9883e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL, 9899c6f6b65d25aa7fe890377a92ea049c8e20da906Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_I7300_MCH_FB0, 990fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab NULL); 9913e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab if (!pvt->pci_dev_2x_0_fbd_branch[0]) { 992fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_printk(KERN_ERR, 993fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab "MC: 'BRANCH 0' device not found:" 994fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n", 995fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_FB0); 996fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab goto error; 997fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 998fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 9993e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pvt->pci_dev_2x_0_fbd_branch[1] = pci_get_device(PCI_VENDOR_ID_INTEL, 1000fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab PCI_DEVICE_ID_INTEL_I7300_MCH_FB1, 1001fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab NULL); 10023e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab if (!pvt->pci_dev_2x_0_fbd_branch[1]) { 1003fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_printk(KERN_ERR, 1004fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab "MC: 'BRANCH 1' device not found:" 1005fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab "vendor 0x%x device 0x%x Func 0 " 1006fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab "(broken BIOS?)\n", 1007fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab PCI_VENDOR_ID_INTEL, 1008fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab PCI_DEVICE_ID_INTEL_I7300_MCH_FB1); 1009fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab goto error; 1010fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 1011fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1012fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return 0; 1013fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1014fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehaberror: 1015fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_put_devices(mci); 1016fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return -ENODEV; 1017fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 1018fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1019d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 1020d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_init_one() - Probe for one instance of the device 1021d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @pdev: struct pci_dev pointer 1022d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @id: struct pci_device_id pointer - currently unused 1023fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 10249b3c6e85c2cfa731cf67d5a8c49f7d8c60ec0b04Greg Kroah-Hartmanstatic int i7300_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 1025fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 1026fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct mem_ctl_info *mci; 102770e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab struct edac_mc_layer layers[3]; 1028fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct i7300_pvt *pvt; 1029d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab int rc; 1030fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1031d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab /* wake up device */ 1032d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab rc = pci_enable_device(pdev); 1033d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab if (rc == -EIO) 1034d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab return rc; 1035fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1036956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n", 1037956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches pdev->bus->number, 1038956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 1039fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1040fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* We only are looking for func 0 of the set */ 1041fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (PCI_FUNC(pdev->devfn) != 0) 1042fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return -ENODEV; 1043fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1044fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* allocate a new MC control structure */ 104570e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[0].type = EDAC_MC_LAYER_BRANCH; 104670e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[0].size = MAX_BRANCHES; 104770e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[0].is_virt_csrow = false; 104870e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[1].type = EDAC_MC_LAYER_CHANNEL; 104970e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[1].size = MAX_CH_PER_BRANCH; 105070e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[1].is_virt_csrow = true; 105170e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[2].type = EDAC_MC_LAYER_SLOT; 105270e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[2].size = MAX_SLOTS; 105370e2a8379b6e704b2e8cdfcf151954171c36e779Mauro Carvalho Chehab layers[2].is_virt_csrow = true; 1054ca0907b9e413bb1d1f3ea123b663535b74928846Mauro Carvalho Chehab mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); 1055fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (mci == NULL) 1056fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return -ENOMEM; 1057fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1058956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "MC: mci = %p\n", mci); 1059fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1060fd687502dc8037aa5a4b84c570ada971106574eeMauro Carvalho Chehab mci->pdev = &pdev->dev; /* record ptr to the generic device */ 1061fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1062fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pvt = mci->pvt_info; 10633e57eef64c53d4a45790fb7bb60a4ee6bf2bad30Mauro Carvalho Chehab pvt->pci_dev_16_0_fsb_ctlr = pdev; /* Record this device in our private */ 1064fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 106585580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab pvt->tmp_prt_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); 106685580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab if (!pvt->tmp_prt_buffer) { 106785580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab edac_mc_free(mci); 106885580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab return -ENOMEM; 106985580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab } 107085580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab 1071fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* 'get' the pci devices we want to reserve for our use */ 1072d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab if (i7300_get_devices(mci)) 1073fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab goto fail0; 1074fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1075fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->mc_idx = 0; 1076fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->mtype_cap = MEM_FLAG_FB_DDR2; 1077fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->edac_ctl_cap = EDAC_FLAG_NONE; 1078fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->edac_cap = EDAC_FLAG_NONE; 1079fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->mod_name = "i7300_edac.c"; 1080fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->mod_ver = I7300_REVISION; 1081d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab mci->ctl_name = i7300_devs[0].ctl_name; 1082fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->dev_name = pci_name(pdev); 1083fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->ctl_page_to_phys = NULL; 1084fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1085fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Set the function pointer to an actual operation function */ 1086fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->edac_check = i7300_check_error; 1087fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1088fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* initialize the MC control structure 'csrows' table 1089fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * with the mapping and control information */ 1090fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (i7300_get_mc_regs(mci)) { 1091956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i7300_init_csrows() returned nonzero value\n"); 1092fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ 1093fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } else { 1094956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(1, "MC: Enable error reporting now\n"); 1095fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_enable_error_reporting(mci); 1096fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 1097fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1098fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* add this new MC control structure to EDAC's list of MCs */ 1099fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (edac_mc_add_mc(mci)) { 1100956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); 1101fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* FIXME: perhaps some code should go here that disables error 1102fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * reporting if we just enabled it 1103fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 1104fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab goto fail1; 1105fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 1106fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1107fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_clear_error(mci); 1108fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1109fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* allocating generic PCI control info */ 1110fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); 1111fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (!i7300_pci) { 1112fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab printk(KERN_WARNING 1113fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab "%s(): Unable to create PCI control\n", 1114fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab __func__); 1115fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab printk(KERN_WARNING 1116fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab "%s(): PCI error report via EDAC not setup\n", 1117fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab __func__); 1118fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab } 1119fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1120fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return 0; 1121fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1122fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Error exit unwinding stack */ 1123fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabfail1: 1124fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1125fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_put_devices(mci); 1126fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1127fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabfail0: 112885580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab kfree(pvt->tmp_prt_buffer); 1129fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab edac_mc_free(mci); 1130fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return -ENODEV; 1131fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 1132fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1133d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 1134d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_remove_one() - Remove the driver 1135d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * @pdev: struct pci_dev pointer 1136fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 11379b3c6e85c2cfa731cf67d5a8c49f7d8c60ec0b04Greg Kroah-Hartmanstatic void i7300_remove_one(struct pci_dev *pdev) 1138fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 1139fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab struct mem_ctl_info *mci; 114085580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab char *tmp; 1141fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1142956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(0, "\n"); 1143fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1144fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (i7300_pci) 1145fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab edac_pci_release_generic_ctl(i7300_pci); 1146fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1147fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab mci = edac_mc_del_mc(&pdev->dev); 1148fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab if (!mci) 1149fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return; 1150fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 115185580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab tmp = ((struct i7300_pvt *)mci->pvt_info)->tmp_prt_buffer; 115285580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab 1153fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* retrieve references to resources, and free those resources */ 1154fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab i7300_put_devices(mci); 1155fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 115685580ea4f72ce08e4d9140a3bb22806185a0bba9Mauro Carvalho Chehab kfree(tmp); 1157fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab edac_mc_free(mci); 1158fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 1159fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1160fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab/* 1161d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * pci_device_id: table for which devices we are looking for 1162fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab * 1163d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * Has only 8086:360c PCI ID 1164fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 1165ba935f40979b32924824759111ed95d35469c5faJingoo Hanstatic const struct pci_device_id i7300_pci_tbl[] = { 1166fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)}, 1167fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab {0,} /* 0 terminated list. */ 1168fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab}; 1169fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1170fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho ChehabMODULE_DEVICE_TABLE(pci, i7300_pci_tbl); 1171fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1172fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab/* 1173d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_driver: pci_driver structure for this module 1174fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 1175fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic struct pci_driver i7300_driver = { 1176fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab .name = "i7300_edac", 1177fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab .probe = i7300_init_one, 11789b3c6e85c2cfa731cf67d5a8c49f7d8c60ec0b04Greg Kroah-Hartman .remove = i7300_remove_one, 1179fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab .id_table = i7300_pci_tbl, 1180fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab}; 1181fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1182d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 1183d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_init() - Registers the driver 1184fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 1185fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic int __init i7300_init(void) 1186fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 1187fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab int pci_rc; 1188fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1189956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\n"); 1190fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1191fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab /* Ensure that the OPSTATE is set correctly for POLL or NMI */ 1192fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab opstate_init(); 1193fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1194fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pci_rc = pci_register_driver(&i7300_driver); 1195fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1196fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab return (pci_rc < 0) ? pci_rc : 0; 1197fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 1198fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1199d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab/** 1200d091a6eb177dd3da8f55f8fd73c5b80db0e1656fMauro Carvalho Chehab * i7300_init() - Unregisters the driver 1201fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab */ 1202fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabstatic void __exit i7300_exit(void) 1203fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab{ 1204956b9ba156dbfdb9cede2b2927ddf8be2233b3a7Joe Perches edac_dbg(2, "\n"); 1205fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab pci_unregister_driver(&i7300_driver); 1206fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab} 1207fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1208fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabmodule_init(i7300_init); 1209fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabmodule_exit(i7300_exit); 1210fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1211fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho ChehabMODULE_LICENSE("GPL"); 121237e59f876bc710d67a30b660826a5e83e07101ceMauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab"); 1213fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho ChehabMODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); 1214fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho ChehabMODULE_DESCRIPTION("MC Driver for Intel I7300 memory controllers - " 1215fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab I7300_REVISION); 1216fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehab 1217fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho Chehabmodule_param(edac_op_state, int, 0444); 1218fcaf780b2ad352edaeb1d1c07a6da053266b1eedMauro Carvalho ChehabMODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); 1219