1920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 28375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * Intel 5400 class Memory Controllers kernel module (Seaburg) 3920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 4920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * This file may be distributed under the terms of the 5920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * GNU General Public License. 6920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 7920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Copyright (c) 2008 by: 8920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Ben Woodard <woodard@redhat.com> 9920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Mauro Carvalho Chehab <mchehab@redhat.com> 10920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 11920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Red Hat Inc. http://www.redhat.com 12920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 13920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Forked and adapted from the i5000_edac driver which was 14920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * written by Douglas Thompson Linux Networx <norsk5@xmission.com> 15920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 16920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * This module is based on the following document: 17920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 18920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Intel 5400 Chipset Memory Controller Hub (MCH) - Datasheet 19920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * http://developer.intel.com/design/chipsets/datashts/313070.htm 20920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 21920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 22920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 23920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include <linux/module.h> 24920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include <linux/init.h> 25920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include <linux/pci.h> 26920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include <linux/pci_ids.h> 27920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include <linux/slab.h> 28920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include <linux/edac.h> 29920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include <linux/mmzone.h> 30920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 31920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#include "edac_core.h" 32920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 33920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 34920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Alter this version for the I5400 module when modifications are made 35920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 36152ba3942276c2a240703669ae4a3099e0a79451Michal Marek#define I5400_REVISION " Ver: 1.0.0" 37920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 38920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define EDAC_MOD_STR "i5400_edac" 39920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 40920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define i5400_printk(level, fmt, arg...) \ 41920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab edac_printk(level, "i5400", fmt, ##arg) 42920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 43920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define i5400_mc_printk(mci, level, fmt, arg...) \ 44920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab edac_mc_chipset_printk(mci, level, "i5400", fmt, ##arg) 45920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 46920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Limits for i5400 */ 47920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NUM_MTRS_PER_BRANCH 4 48920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define CHANNELS_PER_BRANCH 2 49156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson#define MAX_DIMMS_PER_CHANNEL NUM_MTRS_PER_BRANCH 50920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MAX_CHANNELS 4 51156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson/* max possible csrows per channel */ 52156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson#define MAX_CSROWS (MAX_DIMMS_PER_CHANNEL) 53920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 54920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Device 16, 55920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Function 0: System Address 56920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Function 1: Memory Branch Map, Control, Errors Register 57920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Function 2: FSB Error Registers 58920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 598375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * All 3 functions of Device 16 (0,1,2) share the SAME DID and 608375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * uses PCI_DEVICE_ID_INTEL_5400_ERR for device 16 (0,1,2), 618375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * PCI_DEVICE_ID_INTEL_5400_FBD0 and PCI_DEVICE_ID_INTEL_5400_FBD1 628375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * for device 21 (0,1). 63920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 64920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 65920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* OFFSETS for Function 0 */ 66920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */ 67920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MAXCH 0x56 /* Max Channel Number */ 68920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */ 69920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 70920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* OFFSETS for Function 1 */ 71920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define TOLM 0x6C 72920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define REDMEMB 0x7C 73920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3fe00) /* bits [17:9] indicate ODD, [8:0] indicate EVEN */ 74920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MIR0 0x80 75920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MIR1 0x84 76920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define AMIR0 0x8c 77920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define AMIR1 0x90 78920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 79920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Fatal error registers */ 80920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define FERR_FAT_FBD 0x98 /* also called as FERR_FAT_FB_DIMM at datasheet */ 81920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define FERR_FAT_FBDCHAN (3<<28) /* channel index where the highest-order error occurred */ 82920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 83920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NERR_FAT_FBD 0x9c 84920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define FERR_NF_FBD 0xa0 /* also called as FERR_NFAT_FB_DIMM at datasheet */ 85920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 86920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Non-fatal error register */ 87920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NERR_NF_FBD 0xa4 88920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 89920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Enable error mask */ 90920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define EMASK_FBD 0xa8 91920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 92920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERR0_FBD 0xac 93920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERR1_FBD 0xb0 94920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERR2_FBD 0xb4 95920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MCERR_FBD 0xb8 96920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 97920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* No OFFSETS for Device 16 Function 2 */ 98920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 99920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 100920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Device 21, 101920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Function 0: Memory Map Branch 0 102920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 103920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Device 22, 104920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Function 0: Memory Map Branch 1 105920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 106920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 107920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* OFFSETS for Function 0 */ 108920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define AMBPRESENT_0 0x64 109920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define AMBPRESENT_1 0x66 110920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR0 0x80 111920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR1 0x82 112920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR2 0x84 113920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR3 0x86 114920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 115920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* OFFSETS for Function 1 */ 116920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECFGLOG 0x74 117920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECFGLOG 0x78 118920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECMEMA 0xbe 119920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECMEMB 0xc0 120920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECFB_DIMMA 0xc4 121920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECFB_DIMMB 0xc8 122920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECFB_DIMMC 0xcc 123920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECFB_DIMMD 0xd0 124920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECFB_DIMME 0xd4 125920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define NRECFB_DIMMF 0xd8 126920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define REDMEMA 0xdC 127920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECMEMA 0xf0 128920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECMEMB 0xf4 129920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECFB_DIMMA 0xf8 130920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECFB_DIMMB 0xec 131920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECFB_DIMMC 0xf0 132920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECFB_DIMMD 0xf4 133920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECFB_DIMME 0xf8 134920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define RECFB_DIMMF 0xfC 135920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 136920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 137920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Error indicator bits and masks 138920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Error masks are according with Table 5-17 of i5400 datasheet 139920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 140920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 141920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabenum error_mask { 142920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M1 = 1<<0, /* Memory Write error on non-redundant retry */ 143920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M2 = 1<<1, /* Memory or FB-DIMM configuration CRC read error */ 144920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M3 = 1<<2, /* Reserved */ 145920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M4 = 1<<3, /* Uncorrectable Data ECC on Replay */ 146920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M5 = 1<<4, /* Aliased Uncorrectable Non-Mirrored Demand Data ECC */ 147920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M6 = 1<<5, /* Unsupported on i5400 */ 148920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M7 = 1<<6, /* Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */ 149920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M8 = 1<<7, /* Aliased Uncorrectable Patrol Data ECC */ 150920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M9 = 1<<8, /* Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC */ 151920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M10 = 1<<9, /* Unsupported on i5400 */ 152920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M11 = 1<<10, /* Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */ 153920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M12 = 1<<11, /* Non-Aliased Uncorrectable Patrol Data ECC */ 154920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M13 = 1<<12, /* Memory Write error on first attempt */ 155920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M14 = 1<<13, /* FB-DIMM Configuration Write error on first attempt */ 156920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M15 = 1<<14, /* Memory or FB-DIMM configuration CRC read error */ 157920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M16 = 1<<15, /* Channel Failed-Over Occurred */ 158920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M17 = 1<<16, /* Correctable Non-Mirrored Demand Data ECC */ 159920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M18 = 1<<17, /* Unsupported on i5400 */ 160920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M19 = 1<<18, /* Correctable Resilver- or Spare-Copy Data ECC */ 161920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M20 = 1<<19, /* Correctable Patrol Data ECC */ 162920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M21 = 1<<20, /* FB-DIMM Northbound parity error on FB-DIMM Sync Status */ 163920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M22 = 1<<21, /* SPD protocol Error */ 164920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M23 = 1<<22, /* Non-Redundant Fast Reset Timeout */ 165920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M24 = 1<<23, /* Refresh error */ 166920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M25 = 1<<24, /* Memory Write error on redundant retry */ 167920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M26 = 1<<25, /* Redundant Fast Reset Timeout */ 168920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M27 = 1<<26, /* Correctable Counter Threshold Exceeded */ 169920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M28 = 1<<27, /* DIMM-Spare Copy Completed */ 170920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M29 = 1<<28, /* DIMM-Isolation Completed */ 171920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 172920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 173920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 174920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Names to translate bit error into something useful 175920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1768375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehabstatic const char *error_name[] = { 177920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [0] = "Memory Write error on non-redundant retry", 178920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [1] = "Memory or FB-DIMM configuration CRC read error", 179920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Reserved */ 180920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [3] = "Uncorrectable Data ECC on Replay", 181920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [4] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", 1828375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab /* M6 Unsupported on i5400 */ 183920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [6] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", 184920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [7] = "Aliased Uncorrectable Patrol Data ECC", 185920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [8] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC", 1868375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab /* M10 Unsupported on i5400 */ 187920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [10] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", 188920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [11] = "Non-Aliased Uncorrectable Patrol Data ECC", 189920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [12] = "Memory Write error on first attempt", 190920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [13] = "FB-DIMM Configuration Write error on first attempt", 191920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [14] = "Memory or FB-DIMM configuration CRC read error", 192920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [15] = "Channel Failed-Over Occurred", 193920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [16] = "Correctable Non-Mirrored Demand Data ECC", 1948375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab /* M18 Unsupported on i5400 */ 195920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [18] = "Correctable Resilver- or Spare-Copy Data ECC", 196920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [19] = "Correctable Patrol Data ECC", 197920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [20] = "FB-DIMM Northbound parity error on FB-DIMM Sync Status", 198920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [21] = "SPD protocol Error", 199920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [22] = "Non-Redundant Fast Reset Timeout", 200920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [23] = "Refresh error", 201920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [24] = "Memory Write error on redundant retry", 202920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [25] = "Redundant Fast Reset Timeout", 203920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [26] = "Correctable Counter Threshold Exceeded", 204920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [27] = "DIMM-Spare Copy Completed", 205920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab [28] = "DIMM-Isolation Completed", 206920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 207920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 208920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Fatal errors */ 209920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_FAT_MASK (EMASK_M1 | \ 210920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M2 | \ 211920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M23) 212920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 213920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Correctable errors */ 214920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_NF_CORRECTABLE (EMASK_M27 | \ 215920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M20 | \ 216920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M19 | \ 217920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M18 | \ 218920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M17 | \ 219920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M16) 220920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_NF_DIMM_SPARE (EMASK_M29 | \ 221920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M28) 222920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_NF_SPD_PROTOCOL (EMASK_M22) 223920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_NF_NORTH_CRC (EMASK_M21) 224920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 225920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Recoverable errors */ 226920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_NF_RECOVERABLE (EMASK_M26 | \ 227920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M25 | \ 228920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M24 | \ 229920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M15 | \ 230920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M14 | \ 231920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M13 | \ 232920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M12 | \ 233920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M11 | \ 234920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M9 | \ 235920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M8 | \ 236920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M7 | \ 237920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab EMASK_M5) 238920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 239920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* uncorrectable errors */ 240920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_NF_UNCORRECTABLE (EMASK_M4) 241920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 242920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* mask to all non-fatal errors */ 243920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ERROR_NF_MASK (ERROR_NF_CORRECTABLE | \ 244920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ERROR_NF_UNCORRECTABLE | \ 245920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ERROR_NF_RECOVERABLE | \ 246920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ERROR_NF_DIMM_SPARE | \ 247920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ERROR_NF_SPD_PROTOCOL | \ 248920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ERROR_NF_NORTH_CRC) 249920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 250920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 251920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Define error masks for the several registers 252920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 253920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 254920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Enable all fatal and non fatal errors */ 255920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define ENABLE_EMASK_ALL (ERROR_FAT_MASK | ERROR_NF_MASK) 256920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 257920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* mask for fatal error registers */ 258920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define FERR_FAT_MASK ERROR_FAT_MASK 259920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 260920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* masks for non-fatal error register */ 2618375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehabstatic inline int to_nf_mask(unsigned int mask) 2628375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab{ 2638375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab return (mask & EMASK_M29) | (mask >> 3); 2648375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab}; 2658375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab 2668375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehabstatic inline int from_nf_ferr(unsigned int mask) 2678375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab{ 2688375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab return (mask & EMASK_M29) | /* Bit 28 */ 2698375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab (mask & ((1 << 28) - 1) << 3); /* Bits 0 to 27 */ 2708375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab}; 271920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 2728375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define FERR_NF_MASK to_nf_mask(ERROR_NF_MASK) 2738375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define FERR_NF_CORRECTABLE to_nf_mask(ERROR_NF_CORRECTABLE) 2748375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define FERR_NF_DIMM_SPARE to_nf_mask(ERROR_NF_DIMM_SPARE) 2758375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define FERR_NF_SPD_PROTOCOL to_nf_mask(ERROR_NF_SPD_PROTOCOL) 2768375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define FERR_NF_NORTH_CRC to_nf_mask(ERROR_NF_NORTH_CRC) 2778375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define FERR_NF_RECOVERABLE to_nf_mask(ERROR_NF_RECOVERABLE) 2788375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define FERR_NF_UNCORRECTABLE to_nf_mask(ERROR_NF_UNCORRECTABLE) 279920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 280920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Defines to extract the vaious fields from the 281920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * MTRx - Memory Technology Registers 282920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 283920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 10)) 284920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 9)) 2858375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 8)) ? 8 : 4) 2868375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab#define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 6)) ? 8 : 4) 287920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DRAM_BANKS_ADDR_BITS(mtr) ((MTR_DRAM_BANKS(mtr) == 8) ? 3 : 2) 288920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMM_RANK(mtr) (((mtr) >> 5) & 0x1) 289920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMM_RANK_ADDR_BITS(mtr) (MTR_DIMM_RANK(mtr) ? 2 : 1) 290920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3) 291920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13) 292920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) 293920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) 294920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 295920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* This applies to FERR_NF_FB-DIMM as well as FERR_FAT_FB-DIMM */ 296920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int extract_fbdchan_indx(u32 x) 297920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 298920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return (x>>28) & 0x3; 299920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 300920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 301920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#ifdef CONFIG_EDAC_DEBUG 302920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* MTR NUMROW */ 3038375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehabstatic const char *numrow_toString[] = { 304920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "8,192 - 13 rows", 305920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "16,384 - 14 rows", 306920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "32,768 - 15 rows", 307920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "65,536 - 16 rows" 308920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 309920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 310920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* MTR NUMCOL */ 3118375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehabstatic const char *numcol_toString[] = { 312920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "1,024 - 10 columns", 313920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "2,048 - 11 columns", 314920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "4,096 - 12 columns", 315920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "reserved" 316920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 317920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab#endif 318920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 319920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Device name and register DID (Device ID) */ 320920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstruct i5400_dev_info { 321920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab const char *ctl_name; /* name for this device */ 322920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 fsb_mapping_errors; /* DID for the branchmap,control */ 323920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 324920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 325920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* Table of devices attributes supported by this driver */ 326920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic const struct i5400_dev_info i5400_devs[] = { 327920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab { 328920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab .ctl_name = "I5400", 329920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_5400_ERR, 330920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab }, 331920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 332920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 333920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstruct i5400_dimm_info { 334920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int megabytes; /* size, 0 means not present */ 335920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 336920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 337920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* driver private data structure */ 338920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstruct i5400_pvt { 339920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct pci_dev *system_address; /* 16.0 */ 340920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct pci_dev *branchmap_werrors; /* 16.1 */ 341920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct pci_dev *fsb_error_regs; /* 16.2 */ 342920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct pci_dev *branch_0; /* 21.0 */ 343920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct pci_dev *branch_1; /* 22.0 */ 344920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 345920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 tolm; /* top of low memory */ 346920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u64 ambase; /* AMB BAR */ 347920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 348920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 mir0, mir1; 349920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 3508375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab u16 b0_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */ 351920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 b0_ambpresent0; /* Branch 0, Channel 0 */ 352920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 b0_ambpresent1; /* Brnach 0, Channel 1 */ 353920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 3548375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab u16 b1_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */ 355920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 b1_ambpresent0; /* Branch 1, Channel 8 */ 356920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 b1_ambpresent1; /* Branch 1, Channel 1 */ 357920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 358920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* DIMM information matrix, allocating architecture maximums */ 359920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_dimm_info dimm_info[MAX_CSROWS][MAX_CHANNELS]; 360920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 361920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Actual values for this controller */ 362920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int maxch; /* Max channels */ 363920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int maxdimmperch; /* Max DIMMs per channel */ 364920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 365920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 366920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* I5400 MCH error information retrieved from Hardware */ 367920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstruct i5400_error_info { 368920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* These registers are always read from the MC */ 369920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 ferr_fat_fbd; /* First Errors Fatal */ 370920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 nerr_fat_fbd; /* Next Errors Fatal */ 371920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 ferr_nf_fbd; /* First Errors Non-Fatal */ 372920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 nerr_nf_fbd; /* Next Errors Non-Fatal */ 373920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 374920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* These registers are input ONLY if there was a Recoverable Error */ 375920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 redmemb; /* Recoverable Mem Data Error log B */ 376920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 recmema; /* Recoverable Mem Error log A */ 377920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 recmemb; /* Recoverable Mem Error log B */ 378920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 3798375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab /* These registers are input ONLY if there was a Non-Rec Error */ 380920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 nrecmema; /* Non-Recoverable Mem log A */ 381920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 nrecmemb; /* Non-Recoverable Mem log B */ 382920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 383920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 384920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 385920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* note that nrec_rdwr changed from NRECMEMA to NRECMEMB between the 5000 and 386920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 5400 better to use an inline function than a macro in this case */ 387920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int nrec_bank(struct i5400_error_info *info) 388920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 389920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return ((info->nrecmema) >> 12) & 0x7; 390920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 391920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int nrec_rank(struct i5400_error_info *info) 392920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 393920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return ((info->nrecmema) >> 8) & 0xf; 394920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 395920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int nrec_buf_id(struct i5400_error_info *info) 396920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 397920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return ((info->nrecmema)) & 0xff; 398920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 399920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int nrec_rdwr(struct i5400_error_info *info) 400920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 401920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return (info->nrecmemb) >> 31; 402920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 403920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* This applies to both NREC and REC string so it can be used with nrec_rdwr 404920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab and rec_rdwr */ 405920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline const char *rdwr_str(int rdwr) 406920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 407920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return rdwr ? "Write" : "Read"; 408920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 409920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int nrec_cas(struct i5400_error_info *info) 410920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 411920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return ((info->nrecmemb) >> 16) & 0x1fff; 412920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 413920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int nrec_ras(struct i5400_error_info *info) 414920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 415920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return (info->nrecmemb) & 0xffff; 416920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 417920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int rec_bank(struct i5400_error_info *info) 418920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 419920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return ((info->recmema) >> 12) & 0x7; 420920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 421920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int rec_rank(struct i5400_error_info *info) 422920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 423920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return ((info->recmema) >> 8) & 0xf; 424920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 425920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int rec_rdwr(struct i5400_error_info *info) 426920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 427920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return (info->recmemb) >> 31; 428920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 429920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int rec_cas(struct i5400_error_info *info) 430920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 431920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return ((info->recmemb) >> 16) & 0x1fff; 432920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 433920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic inline int rec_ras(struct i5400_error_info *info) 434920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 435920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return (info->recmemb) & 0xffff; 436920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 437920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 438920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic struct edac_pci_ctl_info *i5400_pci; 439920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 440920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 441920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_get_error_info Retrieve the hardware error information from 442920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * the hardware and cache it in the 'info' 443920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * structure 444920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 445920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_get_error_info(struct mem_ctl_info *mci, 446920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_error_info *info) 447920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 448920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_pvt *pvt; 449920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 value; 450920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 451920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt = mci->pvt_info; 452920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 453920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* read in the 1st FATAL error register */ 454920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->branchmap_werrors, FERR_FAT_FBD, &value); 455920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 456920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Mask only the bits that the doc says are valid 457920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 458920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab value &= (FERR_FAT_FBDCHAN | FERR_FAT_MASK); 459920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 460920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* If there is an error, then read in the 461920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab NEXT FATAL error register and the Memory Error Log Register A 462920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 463920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (value & FERR_FAT_MASK) { 464920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->ferr_fat_fbd = value; 465920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 466920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* harvest the various error data we need */ 467920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->branchmap_werrors, 468920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab NERR_FAT_FBD, &info->nerr_fat_fbd); 469920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branchmap_werrors, 470920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab NRECMEMA, &info->nrecmema); 471920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branchmap_werrors, 472920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab NRECMEMB, &info->nrecmemb); 473920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 474920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Clear the error bits, by writing them back */ 475920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_write_config_dword(pvt->branchmap_werrors, 476920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab FERR_FAT_FBD, value); 477920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } else { 478920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->ferr_fat_fbd = 0; 479920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->nerr_fat_fbd = 0; 480920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->nrecmema = 0; 481920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->nrecmemb = 0; 482920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 483920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 484920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* read in the 1st NON-FATAL error register */ 485920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->branchmap_werrors, FERR_NF_FBD, &value); 486920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 487920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* If there is an error, then read in the 1st NON-FATAL error 488920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * register as well */ 489920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (value & FERR_NF_MASK) { 490920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->ferr_nf_fbd = value; 491920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 492920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* harvest the various error data we need */ 493920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->branchmap_werrors, 494920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab NERR_NF_FBD, &info->nerr_nf_fbd); 495920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branchmap_werrors, 496920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab RECMEMA, &info->recmema); 497920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->branchmap_werrors, 498920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab RECMEMB, &info->recmemb); 499920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->branchmap_werrors, 500920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab REDMEMB, &info->redmemb); 501920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 502920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Clear the error bits, by writing them back */ 503920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_write_config_dword(pvt->branchmap_werrors, 504920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab FERR_NF_FBD, value); 505920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } else { 506920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->ferr_nf_fbd = 0; 507920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->nerr_nf_fbd = 0; 508920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->recmema = 0; 509920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->recmemb = 0; 510920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab info->redmemb = 0; 511920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 512920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 513920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 514920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 515920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci, 516920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * struct i5400_error_info *info, 517920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * int handle_errors); 518920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 519920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * handle the Intel FATAL and unrecoverable errors, if any 520920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 521920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci, 522920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_error_info *info, 523920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab unsigned long allErrors) 524920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 525920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80]; 526920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int branch; 527920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int channel; 528920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int bank; 529920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int buf_id; 530920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int rank; 531920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int rdwr; 532920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int ras, cas; 533920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int errnum; 534920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab char *type = NULL; 535920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 536920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!allErrors) 537920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return; /* if no error, return now */ 538920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 539920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (allErrors & ERROR_FAT_MASK) 540920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab type = "FATAL"; 541920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab else if (allErrors & FERR_NF_UNCORRECTABLE) 542920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab type = "NON-FATAL uncorrected"; 543920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab else 544920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab type = "NON-FATAL recoverable"; 545920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 546920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* ONLY ONE of the possible error bits will be set, as per the docs */ 547920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 548920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab branch = extract_fbdchan_indx(info->ferr_fat_fbd); 549920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab channel = branch; 550920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 551920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Use the NON-Recoverable macros to extract data */ 552920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab bank = nrec_bank(info); 553920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rank = nrec_rank(info); 554920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab buf_id = nrec_buf_id(info); 555920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rdwr = nrec_rdwr(info); 556920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ras = nrec_ras(info); 557920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab cas = nrec_cas(info); 558920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 559920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf0("\t\tCSROW= %d Channels= %d,%d (Branch= %d " 560920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n", 561920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rank, channel, channel + 1, branch >> 1, bank, 562920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab buf_id, rdwr_str(rdwr), ras, cas); 563920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 564920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Only 1 bit will be on */ 565920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); 566920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 567920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Form out message */ 568920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab snprintf(msg, sizeof(msg), 5698375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab "%s (Branch=%d DRAM-Bank=%d Buffer ID = %d RDWR=%s " 5708375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab "RAS=%d CAS=%d %s Err=0x%lx (%s))", 5718375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab type, branch >> 1, bank, buf_id, rdwr_str(rdwr), ras, cas, 5728375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab type, allErrors, error_name[errnum]); 573920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 574920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Call the helper to output message */ 575920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); 576920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 577920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 578920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 579920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_process_fatal_error_info(struct mem_ctl_info *mci, 580920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * struct i5400_error_info *info, 581920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * int handle_errors); 582920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 583920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * handle the Intel NON-FATAL errors, if any 584920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 585920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, 586920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_error_info *info) 587920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 588920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80]; 589920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab unsigned long allErrors; 590920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int branch; 591920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int channel; 592920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int bank; 593920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int rank; 594920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int rdwr; 595920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int ras, cas; 596920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int errnum; 597920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 598920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* mask off the Error bits that are possible */ 5998375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab allErrors = from_nf_ferr(info->ferr_nf_fbd & FERR_NF_MASK); 600920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!allErrors) 601920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return; /* if no error, return now */ 602920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 603920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* ONLY ONE of the possible error bits will be set, as per the docs */ 604920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 605920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (allErrors & (ERROR_NF_UNCORRECTABLE | ERROR_NF_RECOVERABLE)) { 606920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_proccess_non_recoverable_info(mci, info, allErrors); 607920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return; 608920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 609920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 610920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Correctable errors */ 611920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (allErrors & ERROR_NF_CORRECTABLE) { 612920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf0("\tCorrected bits= 0x%lx\n", allErrors); 613920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 614920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab branch = extract_fbdchan_indx(info->ferr_nf_fbd); 615920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 616920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab channel = 0; 617920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (REC_ECC_LOCATOR_ODD(info->redmemb)) 618920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab channel = 1; 619920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 620920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Convert channel to be based from zero, instead of 621920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * from branch base of 0 */ 622920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab channel += branch; 623920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 624920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab bank = rec_bank(info); 625920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rank = rec_rank(info); 626920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rdwr = rec_rdwr(info); 627920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ras = rec_ras(info); 628920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab cas = rec_cas(info); 629920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 630920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Only 1 bit will be on */ 631920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); 632920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 633920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf0("\t\tCSROW= %d Channel= %d (Branch %d " 634920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", 635920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rank, channel, branch >> 1, bank, 636920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rdwr_str(rdwr), ras, cas); 637920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 638920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Form out message */ 639920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab snprintf(msg, sizeof(msg), 6408375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab "Corrected error (Branch=%d DRAM-Bank=%d RDWR=%s " 6418375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab "RAS=%d CAS=%d, CE Err=0x%lx (%s))", 6428375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab branch >> 1, bank, rdwr_str(rdwr), ras, cas, 6438375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab allErrors, error_name[errnum]); 644920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 645920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Call the helper to output message */ 646920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab edac_mc_handle_fbd_ce(mci, rank, channel, msg); 647920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 648920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return; 649920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 650920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 65125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Miscellaneous errors */ 652920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); 653920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 654920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab branch = extract_fbdchan_indx(info->ferr_nf_fbd); 655920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 656920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_mc_printk(mci, KERN_EMERG, 657920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "Non-Fatal misc error (Branch=%d Err=%#lx (%s))", 658920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab branch >> 1, allErrors, error_name[errnum]); 659920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 660920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 661920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 662920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_process_error_info Process the error info that is 663920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * in the 'info' structure, previously retrieved from hardware 664920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 665920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_process_error_info(struct mem_ctl_info *mci, 666920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_error_info *info) 667920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ u32 allErrors; 668920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 669920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* First handle any fatal errors that occurred */ 670920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab allErrors = (info->ferr_fat_fbd & FERR_FAT_MASK); 671920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_proccess_non_recoverable_info(mci, info, allErrors); 672920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 673920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* now handle any non-fatal errors that occurred */ 674920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_process_nonfatal_error_info(mci, info); 675920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 676920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 677920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 678920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_clear_error Retrieve any error from the hardware 679920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * but do NOT process that error. 680920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Used for 'clearing' out of previous errors 681920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Called by the Core module. 682920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 683920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_clear_error(struct mem_ctl_info *mci) 684920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 685920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_error_info info; 686920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 687920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_get_error_info(mci, &info); 688920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 689920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 690920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 691920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_check_error Retrieve and process errors reported by the 692920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * hardware. Called by the Core module. 693920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 694920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_check_error(struct mem_ctl_info *mci) 695920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 696920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_error_info info; 69763ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); 698920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_get_error_info(mci, &info); 699920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_process_error_info(mci, &info); 700920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 701920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 702920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 703920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_put_devices 'put' all the devices that we have 704920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * reserved via 'get' 705920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 706920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_put_devices(struct mem_ctl_info *mci) 707920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 708920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_pvt *pvt; 709920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 710920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt = mci->pvt_info; 711920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 712920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Decrement usage count for devices */ 7138375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab pci_dev_put(pvt->branch_1); 7148375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab pci_dev_put(pvt->branch_0); 7158375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab pci_dev_put(pvt->fsb_error_regs); 7168375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab pci_dev_put(pvt->branchmap_werrors); 717920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 718920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 719920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 720920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_get_devices Find and perform 'get' operation on the MCH's 721920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * device/functions we want to reference for this driver 722920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 723920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Need to 'get' device 16 func 1 and func 2 724920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 725920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) 726920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 727920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_pvt *pvt; 728920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct pci_dev *pdev; 729920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 730920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt = mci->pvt_info; 731920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->branchmap_werrors = NULL; 732920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->fsb_error_regs = NULL; 733920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->branch_0 = NULL; 734920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->branch_1 = NULL; 735920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 736920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Attempt to 'get' the MCH register we want */ 737920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pdev = NULL; 7380142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab while (1) { 739920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 740920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_5400_ERR, pdev); 741920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!pdev) { 742920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* End of list, leave */ 743920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_printk(KERN_ERR, 744920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "'system address,Process Bus' " 745920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "device not found:" 7460142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab "vendor 0x%x device 0x%x ERR func 1 " 747920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "(broken BIOS?)\n", 748920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_VENDOR_ID_INTEL, 749920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_5400_ERR); 7500142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab return -ENODEV; 751920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 752920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 7530142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab /* Store device 16 func 1 */ 7540142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab if (PCI_FUNC(pdev->devfn) == 1) 755920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab break; 7560142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab } 7570142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pvt->branchmap_werrors = pdev; 7580142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab 7590142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pdev = NULL; 7600142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab while (1) { 7610142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 7620142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_5400_ERR, pdev); 7630142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab if (!pdev) { 7640142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab /* End of list, leave */ 7650142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab i5400_printk(KERN_ERR, 7660142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab "'system address,Process Bus' " 7670142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab "device not found:" 7680142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab "vendor 0x%x device 0x%x ERR func 2 " 7690142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab "(broken BIOS?)\n", 7700142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab PCI_VENDOR_ID_INTEL, 7710142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_5400_ERR); 7720142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab 7730142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pci_dev_put(pvt->branchmap_werrors); 7740142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab return -ENODEV; 775920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 7760142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab 7770142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab /* Store device 16 func 2 */ 7780142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab if (PCI_FUNC(pdev->devfn) == 2) 7790142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab break; 780920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 7810142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pvt->fsb_error_regs = pdev; 782920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 783920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", 784920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_name(pvt->system_address), 785920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->system_address->vendor, pvt->system_address->device); 786920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", 787920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_name(pvt->branchmap_werrors), 788920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device); 789920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", 790920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_name(pvt->fsb_error_regs), 791920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); 792920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 793920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->branch_0 = pci_get_device(PCI_VENDOR_ID_INTEL, 794920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_5400_FBD0, NULL); 795920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!pvt->branch_0) { 796920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_printk(KERN_ERR, 797920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "MC: 'BRANCH 0' device not found:" 798920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n", 799920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0); 8000142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab 8010142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pci_dev_put(pvt->fsb_error_regs); 8020142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pci_dev_put(pvt->branchmap_werrors); 8030142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab return -ENODEV; 804920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 805920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 806920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* If this device claims to have more than 2 channels then 807920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * fetch Branch 1's information 808920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 809920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (pvt->maxch < CHANNELS_PER_BRANCH) 810920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return 0; 811920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 812920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->branch_1 = pci_get_device(PCI_VENDOR_ID_INTEL, 813920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_5400_FBD1, NULL); 814920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!pvt->branch_1) { 815920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_printk(KERN_ERR, 816920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "MC: 'BRANCH 1' device not found:" 817920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "vendor 0x%x device 0x%x Func 0 " 818920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "(broken BIOS?)\n", 819920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_VENDOR_ID_INTEL, 820920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_DEVICE_ID_INTEL_5400_FBD1); 8210142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab 8220142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pci_dev_put(pvt->branch_0); 8230142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pci_dev_put(pvt->fsb_error_regs); 8240142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab pci_dev_put(pvt->branchmap_werrors); 8250142877aa4e54dd9943fb727e9b386c36c8e3ab7Mauro Carvalho Chehab return -ENODEV; 826920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 827920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 828920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return 0; 829920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 830920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 831920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 832920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * determine_amb_present 833920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 8348375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * the information is contained in NUM_MTRS_PER_BRANCH different 8358375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * registers determining which of the NUM_MTRS_PER_BRANCH requires 8368375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * knowing which channel is in question 837920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 838920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 2 branches, each with 2 channels 839920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * b0_ambpresent0 for channel '0' 840920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * b0_ambpresent1 for channel '1' 841920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * b1_ambpresent0 for channel '2' 842920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * b1_ambpresent1 for channel '3' 843920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 844920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic int determine_amb_present_reg(struct i5400_pvt *pvt, int channel) 845920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 846920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int amb_present; 847920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 848920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (channel < CHANNELS_PER_BRANCH) { 849920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (channel & 0x1) 850920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab amb_present = pvt->b0_ambpresent1; 851920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab else 852920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab amb_present = pvt->b0_ambpresent0; 853920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } else { 854920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (channel & 0x1) 855920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab amb_present = pvt->b1_ambpresent1; 856920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab else 857920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab amb_present = pvt->b1_ambpresent0; 858920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 859920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 860920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return amb_present; 861920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 862920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 863920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 864920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * determine_mtr(pvt, csrow, channel) 865920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 8668375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab * return the proper MTR register as determine by the csrow and desired channel 867920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 868920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel) 869920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 870920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int mtr; 871920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int n; 872920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 873920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* There is one MTR for each slot pair of FB-DIMMs, 874920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab Each slot pair may be at branch 0 or branch 1. 875920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 876156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson n = csrow; 877920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 878920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (n >= NUM_MTRS_PER_BRANCH) { 8798375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab debugf0("ERROR: trying to access an invalid csrow: %d\n", 8808375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab csrow); 881920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return 0; 882920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 883920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 884920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (channel < CHANNELS_PER_BRANCH) 885920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mtr = pvt->b0_mtr[n]; 886920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab else 887920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mtr = pvt->b1_mtr[n]; 888920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 889920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return mtr; 890920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 891920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 892920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 893920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 894920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void decode_mtr(int slot_row, u16 mtr) 895920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 896920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int ans; 897920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 898920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ans = MTR_DIMMS_PRESENT(mtr); 899920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 900920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\tMTR%d=0x%x: DIMMs are %s\n", slot_row, mtr, 901920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ans ? "Present" : "NOT Present"); 902920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!ans) 903920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return; 904920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 905920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); 906920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 907920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tELECTRICAL THROTTLING is %s\n", 9088375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); 909920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 910920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); 911920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); 912920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); 913920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); 914920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 915920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 916920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void handle_channel(struct i5400_pvt *pvt, int csrow, int channel, 917920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_dimm_info *dinfo) 918920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 919920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int mtr; 920920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int amb_present_reg; 921920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int addrBits; 922920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 923920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mtr = determine_mtr(pvt, csrow, channel); 924920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (MTR_DIMMS_PRESENT(mtr)) { 925920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab amb_present_reg = determine_amb_present_reg(pvt, channel); 926920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 927920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Determine if there is a DIMM present in this DIMM slot */ 928156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson if (amb_present_reg & (1 << csrow)) { 929156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson /* Start with the number of bits for a Bank 930156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson * on the DRAM */ 931156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr); 932156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson /* Add thenumber of ROW bits */ 933156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr); 934156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson /* add the number of COLUMN bits */ 935156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); 936156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson /* add the number of RANK bits */ 937156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson addrBits += MTR_DIMM_RANK(mtr); 938156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson 939156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson addrBits += 6; /* add 64 bits per DIMM */ 940156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson addrBits -= 20; /* divide by 2^^20 */ 941156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson addrBits -= 3; /* 8 bits per bytes */ 942156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson 943156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson dinfo->megabytes = 1 << addrBits; 944920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 945920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 946920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 947920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 948920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 949920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * calculate_dimm_size 950920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 951920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * also will output a DIMM matrix map, if debug is enabled, for viewing 952920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * how the DIMMs are populated 953920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 954920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void calculate_dimm_size(struct i5400_pvt *pvt) 955920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 956920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_dimm_info *dinfo; 957920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int csrow, max_csrows; 958920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab char *p, *mem_buffer; 959920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int space, n; 960920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int channel; 961920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 962920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* ================= Generate some debug output ================= */ 963920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space = PAGE_SIZE; 964920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mem_buffer = p = kmalloc(space, GFP_KERNEL); 965920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (p == NULL) { 966920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_printk(KERN_ERR, "MC: %s:%s() kmalloc() failed\n", 967920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab __FILE__, __func__); 968920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return; 969920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 970920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 971156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson /* Scan all the actual CSROWS 972920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * and calculate the information for each DIMM 973920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Start with the highest csrow first, to display it first 974920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * and work toward the 0th csrow 975920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 976156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson max_csrows = pvt->maxdimmperch; 977920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (csrow = max_csrows - 1; csrow >= 0; csrow--) { 978920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 979920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* on an odd csrow, first output a 'boundary' marker, 980920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * then reset the message buffer */ 981920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (csrow & 0x1) { 982920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab n = snprintf(p, space, "---------------------------" 983920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "--------------------------------"); 984920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p += n; 985920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space -= n; 986920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("%s\n", mem_buffer); 987920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p = mem_buffer; 988920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space = PAGE_SIZE; 989920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 990920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab n = snprintf(p, space, "csrow %2d ", csrow); 991920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p += n; 992920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space -= n; 993920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 994920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (channel = 0; channel < pvt->maxch; channel++) { 995920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab dinfo = &pvt->dimm_info[csrow][channel]; 996920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab handle_channel(pvt, csrow, channel, dinfo); 997920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab n = snprintf(p, space, "%4d MB | ", dinfo->megabytes); 998920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p += n; 999920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space -= n; 1000920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1001920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("%s\n", mem_buffer); 1002920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p = mem_buffer; 1003920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space = PAGE_SIZE; 1004920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1005920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1006920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Output the last bottom 'boundary' marker */ 1007920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab n = snprintf(p, space, "---------------------------" 1008920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "--------------------------------"); 1009920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p += n; 1010920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space -= n; 1011920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("%s\n", mem_buffer); 1012920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p = mem_buffer; 1013920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space = PAGE_SIZE; 1014920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1015920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* now output the 'channel' labels */ 1016920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab n = snprintf(p, space, " "); 1017920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p += n; 1018920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space -= n; 1019920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (channel = 0; channel < pvt->maxch; channel++) { 1020920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab n = snprintf(p, space, "channel %d | ", channel); 1021920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p += n; 1022920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab space -= n; 1023920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1024920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1025920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* output the last message and free buffer */ 1026920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("%s\n", mem_buffer); 1027920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab kfree(mem_buffer); 1028920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1029920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1030920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1031920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_get_mc_regs read in the necessary registers and 1032920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * cache locally 1033920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 1034920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Fills in the private data members 1035920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1036920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_get_mc_regs(struct mem_ctl_info *mci) 1037920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 1038920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_pvt *pvt; 1039920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 actual_tolm; 1040920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u16 limit; 1041920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int slot_row; 1042920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int maxch; 1043920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int maxdimmperch; 1044920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int way0, way1; 1045920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1046920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt = mci->pvt_info; 1047920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1048920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->system_address, AMBASE, 1049920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab (u32 *) &pvt->ambase); 1050920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32), 1051920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab ((u32 *) &pvt->ambase) + sizeof(u32)); 1052920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1053920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab maxdimmperch = pvt->maxdimmperch; 1054920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab maxch = pvt->maxch; 1055920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1056920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", 1057920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); 1058920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1059920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Get the Branch Map regs */ 1060920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm); 1061920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->tolm >>= 12; 1062920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, 1063920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->tolm); 1064920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1065920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28)); 1066920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n", 1067920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); 1068920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1069920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0); 1070920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1); 1071920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1072920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Get the MIR[0-1] regs */ 1073920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab limit = (pvt->mir0 >> 4) & 0x0fff; 1074920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab way0 = pvt->mir0 & 0x1; 1075920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab way1 = pvt->mir0 & 0x2; 1076920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); 1077920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab limit = (pvt->mir1 >> 4) & 0xfff; 1078920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab way0 = pvt->mir1 & 0x1; 1079920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab way1 = pvt->mir1 & 0x2; 1080920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); 1081920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1082920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Get the set of MTR[0-3] regs by each branch */ 1083920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) { 1084156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson int where = MTR0 + (slot_row * sizeof(u16)); 1085920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1086920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Branch 0 set of MTR registers */ 1087920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branch_0, where, 1088920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab &pvt->b0_mtr[slot_row]); 1089920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1090920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where, 1091920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->b0_mtr[slot_row]); 1092920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1093920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (pvt->maxch < CHANNELS_PER_BRANCH) { 1094920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->b1_mtr[slot_row] = 0; 1095920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab continue; 1096920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1097920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1098920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Branch 1 set of MTR registers */ 1099920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branch_1, where, 1100920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab &pvt->b1_mtr[slot_row]); 1101920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, where, 1102920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->b1_mtr[slot_row]); 1103920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1104920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1105920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Read and dump branch 0's MTRs */ 1106920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\nMemory Technology Registers:\n"); 1107920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2(" Branch 0:\n"); 1108920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) 1109920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab decode_mtr(slot_row, pvt->b0_mtr[slot_row]); 1110920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1111920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branch_0, AMBPRESENT_0, 1112920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab &pvt->b0_ambpresent0); 1113920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); 1114920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branch_0, AMBPRESENT_1, 1115920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab &pvt->b0_ambpresent1); 1116920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); 1117920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1118920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Only if we have 2 branchs (4 channels) */ 1119920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (pvt->maxch < CHANNELS_PER_BRANCH) { 1120920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->b1_ambpresent0 = 0; 1121920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->b1_ambpresent1 = 0; 1122920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } else { 1123920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Read and dump branch 1's MTRs */ 1124920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2(" Branch 1:\n"); 1125920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) 1126920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab decode_mtr(slot_row, pvt->b1_mtr[slot_row]); 1127920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1128920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branch_1, AMBPRESENT_0, 1129920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab &pvt->b1_ambpresent0); 1130920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tAMB-Branch 1-present0 0x%x:\n", 1131920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->b1_ambpresent0); 1132920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_word(pvt->branch_1, AMBPRESENT_1, 1133920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab &pvt->b1_ambpresent1); 1134920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf2("\t\tAMB-Branch 1-present1 0x%x:\n", 1135920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->b1_ambpresent1); 1136920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1137920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1138920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Go and determine the size of each DIMM and place in an 1139920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * orderly matrix */ 1140920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab calculate_dimm_size(pvt); 1141920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1142920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1143920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1144920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_init_csrows Initialize the 'csrows' table within 1145920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * the mci control structure with the 1146920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * addressing of memory. 1147920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 1148920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * return: 1149920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 0 success 1150920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 1 no actual memory found on this MC 1151920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1152920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic int i5400_init_csrows(struct mem_ctl_info *mci) 1153920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 1154920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_pvt *pvt; 1155920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct csrow_info *p_csrow; 1156920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int empty, channel_count; 1157920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int max_csrows; 1158920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int mtr; 1159920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int csrow_megs; 1160920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int channel; 1161920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int csrow; 1162920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1163920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt = mci->pvt_info; 1164920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1165920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab channel_count = pvt->maxch; 1166156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson max_csrows = pvt->maxdimmperch; 1167920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1168920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab empty = 1; /* Assume NO memory */ 1169920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1170920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (csrow = 0; csrow < max_csrows; csrow++) { 1171920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow = &mci->csrows[csrow]; 1172920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1173920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->csrow_idx = csrow; 1174920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1175920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* use branch 0 for the basis */ 1176920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mtr = determine_mtr(pvt, csrow, 0); 1177920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1178920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* if no DIMMS on this row, continue */ 1179920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!MTR_DIMMS_PRESENT(mtr)) 1180920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab continue; 1181920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1182920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* FAKE OUT VALUES, FIXME */ 1183920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->first_page = 0 + csrow * 20; 1184920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->last_page = 9 + csrow * 20; 1185920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->page_mask = 0xFFF; 1186920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1187920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->grain = 8; 1188920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1189920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab csrow_megs = 0; 1190920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab for (channel = 0; channel < pvt->maxch; channel++) 1191920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab csrow_megs += pvt->dimm_info[csrow][channel].megabytes; 1192920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1193920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->nr_pages = csrow_megs << 8; 1194920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1195920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Assume DDR2 for now */ 1196920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->mtype = MEM_FB_DDR2; 1197920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1198920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* ask what device type on this row */ 1199920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (MTR_DRAM_WIDTH(mtr)) 1200920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->dtype = DEV_X8; 1201920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab else 1202920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->dtype = DEV_X4; 1203920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1204920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab p_csrow->edac_mode = EDAC_S8ECD8ED; 1205920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1206920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab empty = 0; 1207920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1208920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1209920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return empty; 1210920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1211920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1212920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1213920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_enable_error_reporting 1214920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Turn on the memory reporting features of the hardware 1215920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1216920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void i5400_enable_error_reporting(struct mem_ctl_info *mci) 1217920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 1218920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_pvt *pvt; 1219920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab u32 fbd_error_mask; 1220920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1221920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt = mci->pvt_info; 1222920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1223920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Read the FBD Error Mask Register */ 1224920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_read_config_dword(pvt->branchmap_werrors, EMASK_FBD, 1225920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab &fbd_error_mask); 1226920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1227920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Enable with a '0' */ 1228920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab fbd_error_mask &= ~(ENABLE_EMASK_ALL); 1229920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1230920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_write_config_dword(pvt->branchmap_werrors, EMASK_FBD, 1231920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab fbd_error_mask); 1232920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1233920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1234920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1235920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_probe1 Probe for ONE instance of device to see if it is 1236920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * present. 1237920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * return: 1238920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 0 for FOUND a device 1239920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * < 0 for error code 1240920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1241920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic int i5400_probe1(struct pci_dev *pdev, int dev_idx) 1242920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 1243920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct mem_ctl_info *mci; 1244920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct i5400_pvt *pvt; 1245920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int num_channels; 1246920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int num_dimms_per_channel; 1247920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int num_csrows; 1248920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 12498375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab if (dev_idx >= ARRAY_SIZE(i5400_devs)) 12508375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab return -EINVAL; 12518375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab 125263ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n", 125363ae96be98fa35bc058805b664ab15433efd553bJoe Perches __FILE__, __func__, 1254920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pdev->bus->number, 1255920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 1256920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1257920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* We only are looking for func 0 of the set */ 1258920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (PCI_FUNC(pdev->devfn) != 0) 1259920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return -ENODEV; 1260920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1261156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson /* As we don't have a motherboard identification routine to determine 1262920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * actual number of slots/dimms per channel, we thus utilize the 1263920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * resource as specified by the chipset. Thus, we might have 1264920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * have more DIMMs per channel than actually on the mobo, but this 126525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * allows the driver to support up to the chipset max, without 1266920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * some fancy mobo determination. 1267920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1268156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson num_dimms_per_channel = MAX_DIMMS_PER_CHANNEL; 1269156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson num_channels = MAX_CHANNELS; 1270156edd4aaa819ec5867ced83c7b8dba9193789eaJeff Roberson num_csrows = num_dimms_per_channel; 1271920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1272920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n", 1273920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab __func__, num_channels, num_dimms_per_channel, num_csrows); 1274920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1275920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* allocate a new MC control structure */ 1276920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0); 1277920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1278920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (mci == NULL) 1279920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return -ENOMEM; 1280920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 128163ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); 1282920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1283920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->dev = &pdev->dev; /* record ptr to the generic device */ 1284920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1285920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt = mci->pvt_info; 1286920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->system_address = pdev; /* Record this device in our private */ 1287920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->maxch = num_channels; 1288920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pvt->maxdimmperch = num_dimms_per_channel; 1289920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1290920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* 'get' the pci devices we want to reserve for our use */ 1291920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (i5400_get_devices(mci, dev_idx)) 1292920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab goto fail0; 1293920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1294920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Time to get serious */ 1295920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_get_mc_regs(mci); /* retrieve the hardware registers */ 1296920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1297920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->mc_idx = 0; 1298920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->mtype_cap = MEM_FLAG_FB_DDR2; 1299920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->edac_ctl_cap = EDAC_FLAG_NONE; 1300920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->edac_cap = EDAC_FLAG_NONE; 1301920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->mod_name = "i5400_edac.c"; 1302920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->mod_ver = I5400_REVISION; 1303920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->ctl_name = i5400_devs[dev_idx].ctl_name; 1304920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->dev_name = pci_name(pdev); 1305920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->ctl_page_to_phys = NULL; 1306920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1307920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Set the function pointer to an actual operation function */ 1308920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->edac_check = i5400_check_error; 1309920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1310920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* initialize the MC control structure 'csrows' table 1311920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * with the mapping and control information */ 1312920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (i5400_init_csrows(mci)) { 1313920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" 1314920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab " because i5400_init_csrows() returned nonzero " 1315920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "value\n"); 1316920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ 1317920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } else { 1318920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab debugf1("MC: Enable error reporting now\n"); 1319920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_enable_error_reporting(mci); 1320920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1321920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1322920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* add this new MC control structure to EDAC's list of MCs */ 1323920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (edac_mc_add_mc(mci)) { 132463ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n", 132563ae96be98fa35bc058805b664ab15433efd553bJoe Perches __FILE__, __func__); 1326920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* FIXME: perhaps some code should go here that disables error 1327920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * reporting if we just enabled it 1328920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1329920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab goto fail1; 1330920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1331920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1332920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_clear_error(mci); 1333920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1334920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* allocating generic PCI control info */ 1335920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); 1336920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!i5400_pci) { 1337920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab printk(KERN_WARNING 1338920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "%s(): Unable to create PCI control\n", 1339920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab __func__); 1340920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab printk(KERN_WARNING 1341920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab "%s(): PCI error report via EDAC not setup\n", 1342920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab __func__); 1343920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab } 1344920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1345920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return 0; 1346920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1347920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Error exit unwinding stack */ 1348920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabfail1: 1349920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1350920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_put_devices(mci); 1351920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1352920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabfail0: 1353920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab edac_mc_free(mci); 1354920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return -ENODEV; 1355920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1356920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1357920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1358920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_init_one constructor for one instance of device 1359920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 1360920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * returns: 1361920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * negative on error 1362920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * count (>= 0) 1363920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1364920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic int __devinit i5400_init_one(struct pci_dev *pdev, 1365920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab const struct pci_device_id *id) 1366920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 1367920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int rc; 1368920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 136963ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf0("MC: %s: %s()\n", __FILE__, __func__); 1370920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1371920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* wake up device */ 1372920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab rc = pci_enable_device(pdev); 1373b425d5c82d9b1fcf788688e556e4dfeca76604daKulikov Vasiliy if (rc) 1374920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return rc; 1375920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1376920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* now probe and enable the device */ 1377920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return i5400_probe1(pdev, id->driver_data); 1378920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1379920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1380920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1381920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_remove_one destructor for one instance of device 1382920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 1383920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1384920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void __devexit i5400_remove_one(struct pci_dev *pdev) 1385920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 1386920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab struct mem_ctl_info *mci; 1387920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 138863ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf0("%s: %s()\n", __FILE__, __func__); 1389920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1390920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (i5400_pci) 1391920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab edac_pci_release_generic_ctl(i5400_pci); 1392920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1393920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab mci = edac_mc_del_mc(&pdev->dev); 1394920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab if (!mci) 1395920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return; 1396920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1397920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* retrieve references to resources, and free those resources */ 1398920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab i5400_put_devices(mci); 1399920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1400920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab edac_mc_free(mci); 1401920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1402920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1403920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1404920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * pci_device_id table for which devices we are looking for 1405920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 1406920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * The "E500P" device is the first device supported. 1407920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 140836c46f31df910b092aaaed27c7c616bb8e2302a1Lionel Debrouxstatic DEFINE_PCI_DEVICE_TABLE(i5400_pci_tbl) = { 1409920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR)}, 1410920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab {0,} /* 0 terminated list. */ 1411920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 1412920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1413920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho ChehabMODULE_DEVICE_TABLE(pci, i5400_pci_tbl); 1414920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1415920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1416920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_driver pci_driver structure for this module 1417920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * 1418920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1419920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic struct pci_driver i5400_driver = { 14208375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab .name = "i5400_edac", 1421920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab .probe = i5400_init_one, 1422920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab .remove = __devexit_p(i5400_remove_one), 1423920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab .id_table = i5400_pci_tbl, 1424920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab}; 1425920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1426920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1427920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_init Module entry function 1428920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Try to initialize this module for its devices 1429920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1430920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic int __init i5400_init(void) 1431920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 1432920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab int pci_rc; 1433920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 143463ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf2("MC: %s: %s()\n", __FILE__, __func__); 1435920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1436920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab /* Ensure that the OPSTATE is set correctly for POLL or NMI */ 1437920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab opstate_init(); 1438920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1439920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_rc = pci_register_driver(&i5400_driver); 1440920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1441920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab return (pci_rc < 0) ? pci_rc : 0; 1442920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1443920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1444920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab/* 1445920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * i5400_exit() Module exit function 1446920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab * Unregister the driver 1447920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab */ 1448920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabstatic void __exit i5400_exit(void) 1449920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab{ 145063ae96be98fa35bc058805b664ab15433efd553bJoe Perches debugf2("MC: %s: %s()\n", __FILE__, __func__); 1451920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab pci_unregister_driver(&i5400_driver); 1452920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab} 1453920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1454920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabmodule_init(i5400_init); 1455920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabmodule_exit(i5400_exit); 1456920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1457920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho ChehabMODULE_LICENSE("GPL"); 14588375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho ChehabMODULE_AUTHOR("Ben Woodard <woodard@redhat.com>"); 14598375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); 14608375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho ChehabMODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); 14618375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho ChehabMODULE_DESCRIPTION("MC Driver for Intel I5400 memory controllers - " 14628375d4909aee4c18798f373ecf24a79f040f75fcMauro Carvalho Chehab I5400_REVISION); 1463920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehab 1464920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho Chehabmodule_param(edac_op_state, int, 0444); 1465920c8df6ac678fdb8c49a6ce2e47a98e62757d77Mauro Carvalho ChehabMODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); 1466