brintos

brintos / linux-shallow public Read only

0
0
Text · 13.6 KiB · 933dcf3 Raw
463 lines · c
1/*2 * Intel 82443BX/GX (440BX/GX chipset) Memory Controller EDAC kernel3 * module (C) 2006 Tim Small4 *5 * This file may be distributed under the terms of the GNU General6 * Public License.7 *8 * Written by Tim Small <tim@buttersideup.com>, based on work by Linux9 * Networx, Thayne Harbaugh, Dan Hollis <goemon at anime dot net> and10 * others.11 *12 * 440GX fix by Jason Uhlenkott <juhlenko@akamai.com>.13 *14 * Written with reference to 82443BX Host Bridge Datasheet:15 * http://download.intel.com/design/chipsets/datashts/29063301.pdf16 * references to this document given in [].17 *18 * This module doesn't support the 440LX, but it may be possible to19 * make it do so (the 440LX's register definitions are different, but20 * not completely so - I haven't studied them in enough detail to know21 * how easy this would be).22 */23 24#include <linux/module.h>25#include <linux/init.h>26 27#include <linux/pci.h>28#include <linux/pci_ids.h>29 30 31#include <linux/edac.h>32#include "edac_module.h"33 34#define EDAC_MOD_STR    "i82443bxgx_edac"35 36/* The 82443BX supports SDRAM, or EDO (EDO for mobile only), "Memory37 * Size: 8 MB to 512 MB (1GB with Registered DIMMs) with eight memory38 * rows" "The 82443BX supports multiple-bit error detection and39 * single-bit error correction when ECC mode is enabled and40 * single/multi-bit error detection when correction is disabled.41 * During writes to the DRAM, the 82443BX generates ECC for the data42 * on a QWord basis. Partial QWord writes require a read-modify-write43 * cycle when ECC is enabled."44*/45 46/* "Additionally, the 82443BX ensures that the data is corrected in47 * main memory so that accumulation of errors is prevented. Another48 * error within the same QWord would result in a double-bit error49 * which is unrecoverable. This is known as hardware scrubbing since50 * it requires no software intervention to correct the data in memory."51 */52 53/* [Also see page 100 (section 4.3), "DRAM Interface"]54 * [Also see page 112 (section 4.6.1.4), ECC]55 */56 57#define I82443BXGX_NR_CSROWS 858#define I82443BXGX_NR_CHANS  159#define I82443BXGX_NR_DIMMS  460 61/* 82443 PCI Device 0 */62#define I82443BXGX_NBXCFG 0x50	/* 32bit register starting at this PCI63				 * config space offset */64#define I82443BXGX_NBXCFG_OFFSET_NON_ECCROW 24	/* Array of bits, zero if65						 * row is non-ECC */66#define I82443BXGX_NBXCFG_OFFSET_DRAM_FREQ 12	/* 2 bits,00=100MHz,10=66 MHz */67 68#define I82443BXGX_NBXCFG_OFFSET_DRAM_INTEGRITY 7	/* 2 bits:       */69#define I82443BXGX_NBXCFG_INTEGRITY_NONE   0x0	/* 00 = Non-ECC */70#define I82443BXGX_NBXCFG_INTEGRITY_EC     0x1	/* 01 = EC (only) */71#define I82443BXGX_NBXCFG_INTEGRITY_ECC    0x2	/* 10 = ECC */72#define I82443BXGX_NBXCFG_INTEGRITY_SCRUB  0x3	/* 11 = ECC + HW Scrub */73 74#define I82443BXGX_NBXCFG_OFFSET_ECC_DIAG_ENABLE  675 76/* 82443 PCI Device 0 */77#define I82443BXGX_EAP   0x80	/* 32bit register starting at this PCI78				 * config space offset, Error Address79				 * Pointer Register */80#define I82443BXGX_EAP_OFFSET_EAP  12	/* High 20 bits of error address */81#define I82443BXGX_EAP_OFFSET_MBE  BIT(1)	/* Err at EAP was multi-bit (W1TC) */82#define I82443BXGX_EAP_OFFSET_SBE  BIT(0)	/* Err at EAP was single-bit (W1TC) */83 84#define I82443BXGX_ERRCMD  0x90	/* 8bit register starting at this PCI85				 * config space offset. */86#define I82443BXGX_ERRCMD_OFFSET_SERR_ON_MBE BIT(1)	/* 1 = enable */87#define I82443BXGX_ERRCMD_OFFSET_SERR_ON_SBE BIT(0)	/* 1 = enable */88 89#define I82443BXGX_ERRSTS  0x91	/* 16bit register starting at this PCI90				 * config space offset. */91#define I82443BXGX_ERRSTS_OFFSET_MBFRE 5	/* 3 bits - first err row multibit */92#define I82443BXGX_ERRSTS_OFFSET_MEF   BIT(4)	/* 1 = MBE occurred */93#define I82443BXGX_ERRSTS_OFFSET_SBFRE 1	/* 3 bits - first err row singlebit */94#define I82443BXGX_ERRSTS_OFFSET_SEF   BIT(0)	/* 1 = SBE occurred */95 96#define I82443BXGX_DRAMC 0x57	/* 8bit register starting at this PCI97				 * config space offset. */98#define I82443BXGX_DRAMC_OFFSET_DT 3	/* 2 bits, DRAM Type */99#define I82443BXGX_DRAMC_DRAM_IS_EDO 0	/* 00 = EDO */100#define I82443BXGX_DRAMC_DRAM_IS_SDRAM 1	/* 01 = SDRAM */101#define I82443BXGX_DRAMC_DRAM_IS_RSDRAM 2	/* 10 = Registered SDRAM */102 103#define I82443BXGX_DRB 0x60	/* 8x 8bit registers starting at this PCI104				 * config space offset. */105 106/* FIXME - don't poll when ECC disabled? */107 108struct i82443bxgx_edacmc_error_info {109	u32 eap;110};111 112static struct edac_pci_ctl_info *i82443bxgx_pci;113 114static struct pci_dev *mci_pdev;	/* init dev: in case that AGP code has115					 * already registered driver116					 */117 118static int i82443bxgx_registered = 1;119 120static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci,121				struct i82443bxgx_edacmc_error_info122				*info)123{124	struct pci_dev *pdev;125	pdev = to_pci_dev(mci->pdev);126	pci_read_config_dword(pdev, I82443BXGX_EAP, &info->eap);127	if (info->eap & I82443BXGX_EAP_OFFSET_SBE)128		/* Clear error to allow next error to be reported [p.61] */129		pci_write_bits32(pdev, I82443BXGX_EAP,130				 I82443BXGX_EAP_OFFSET_SBE,131				 I82443BXGX_EAP_OFFSET_SBE);132 133	if (info->eap & I82443BXGX_EAP_OFFSET_MBE)134		/* Clear error to allow next error to be reported [p.61] */135		pci_write_bits32(pdev, I82443BXGX_EAP,136				 I82443BXGX_EAP_OFFSET_MBE,137				 I82443BXGX_EAP_OFFSET_MBE);138}139 140static int i82443bxgx_edacmc_process_error_info(struct mem_ctl_info *mci,141						struct142						i82443bxgx_edacmc_error_info143						*info, int handle_errors)144{145	int error_found = 0;146	u32 eapaddr, page, pageoffset;147 148	/* bits 30:12 hold the 4kb block in which the error occurred149	 * [p.61] */150	eapaddr = (info->eap & 0xfffff000);151	page = eapaddr >> PAGE_SHIFT;152	pageoffset = eapaddr - (page << PAGE_SHIFT);153 154	if (info->eap & I82443BXGX_EAP_OFFSET_SBE) {155		error_found = 1;156		if (handle_errors)157			edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,158					     page, pageoffset, 0,159					     edac_mc_find_csrow_by_page(mci, page),160					     0, -1, mci->ctl_name, "");161	}162 163	if (info->eap & I82443BXGX_EAP_OFFSET_MBE) {164		error_found = 1;165		if (handle_errors)166			edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,167					     page, pageoffset, 0,168					     edac_mc_find_csrow_by_page(mci, page),169					     0, -1, mci->ctl_name, "");170	}171 172	return error_found;173}174 175static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci)176{177	struct i82443bxgx_edacmc_error_info info;178 179	i82443bxgx_edacmc_get_error_info(mci, &info);180	i82443bxgx_edacmc_process_error_info(mci, &info, 1);181}182 183static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,184				struct pci_dev *pdev,185				enum edac_type edac_mode,186				enum mem_type mtype)187{188	struct csrow_info *csrow;189	struct dimm_info *dimm;190	int index;191	u8 drbar, dramc;192	u32 row_base, row_high_limit, row_high_limit_last;193 194	pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc);195	row_high_limit_last = 0;196	for (index = 0; index < mci->nr_csrows; index++) {197		csrow = mci->csrows[index];198		dimm = csrow->channels[0]->dimm;199 200		pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar);201		edac_dbg(1, "MC%d: Row=%d DRB = %#0x\n",202			 mci->mc_idx, index, drbar);203		row_high_limit = ((u32) drbar << 23);204		/* find the DRAM Chip Select Base address and mask */205		edac_dbg(1, "MC%d: Row=%d, Boundary Address=%#0x, Last = %#0x\n",206			 mci->mc_idx, index, row_high_limit,207			 row_high_limit_last);208 209		/* 440GX goes to 2GB, represented with a DRB of 0. */210		if (row_high_limit_last && !row_high_limit)211			row_high_limit = 1UL << 31;212 213		/* This row is empty [p.49] */214		if (row_high_limit == row_high_limit_last)215			continue;216		row_base = row_high_limit_last;217		csrow->first_page = row_base >> PAGE_SHIFT;218		csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;219		dimm->nr_pages = csrow->last_page - csrow->first_page + 1;220		/* EAP reports in 4kilobyte granularity [61] */221		dimm->grain = 1 << 12;222		dimm->mtype = mtype;223		/* I don't think 440BX can tell you device type? FIXME? */224		dimm->dtype = DEV_UNKNOWN;225		/* Mode is global to all rows on 440BX */226		dimm->edac_mode = edac_mode;227		row_high_limit_last = row_high_limit;228	}229}230 231static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx)232{233	struct mem_ctl_info *mci;234	struct edac_mc_layer layers[2];235	u8 dramc;236	u32 nbxcfg, ecc_mode;237	enum mem_type mtype;238	enum edac_type edac_mode;239 240	edac_dbg(0, "MC:\n");241 242	/* Something is really hosed if PCI config space reads from243	 * the MC aren't working.244	 */245	if (pci_read_config_dword(pdev, I82443BXGX_NBXCFG, &nbxcfg))246		return -EIO;247 248	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;249	layers[0].size = I82443BXGX_NR_CSROWS;250	layers[0].is_virt_csrow = true;251	layers[1].type = EDAC_MC_LAYER_CHANNEL;252	layers[1].size = I82443BXGX_NR_CHANS;253	layers[1].is_virt_csrow = false;254	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);255	if (mci == NULL)256		return -ENOMEM;257 258	edac_dbg(0, "MC: mci = %p\n", mci);259	mci->pdev = &pdev->dev;260	mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR;261	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;262	pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc);263	switch ((dramc >> I82443BXGX_DRAMC_OFFSET_DT) & (BIT(0) | BIT(1))) {264	case I82443BXGX_DRAMC_DRAM_IS_EDO:265		mtype = MEM_EDO;266		break;267	case I82443BXGX_DRAMC_DRAM_IS_SDRAM:268		mtype = MEM_SDR;269		break;270	case I82443BXGX_DRAMC_DRAM_IS_RSDRAM:271		mtype = MEM_RDR;272		break;273	default:274		edac_dbg(0, "Unknown/reserved DRAM type value in DRAMC register!\n");275		mtype = -MEM_UNKNOWN;276	}277 278	if ((mtype == MEM_SDR) || (mtype == MEM_RDR))279		mci->edac_cap = mci->edac_ctl_cap;280	else281		mci->edac_cap = EDAC_FLAG_NONE;282 283	mci->scrub_cap = SCRUB_FLAG_HW_SRC;284	pci_read_config_dword(pdev, I82443BXGX_NBXCFG, &nbxcfg);285	ecc_mode = ((nbxcfg >> I82443BXGX_NBXCFG_OFFSET_DRAM_INTEGRITY) &286		(BIT(0) | BIT(1)));287 288	mci->scrub_mode = (ecc_mode == I82443BXGX_NBXCFG_INTEGRITY_SCRUB)289		? SCRUB_HW_SRC : SCRUB_NONE;290 291	switch (ecc_mode) {292	case I82443BXGX_NBXCFG_INTEGRITY_NONE:293		edac_mode = EDAC_NONE;294		break;295	case I82443BXGX_NBXCFG_INTEGRITY_EC:296		edac_mode = EDAC_EC;297		break;298	case I82443BXGX_NBXCFG_INTEGRITY_ECC:299	case I82443BXGX_NBXCFG_INTEGRITY_SCRUB:300		edac_mode = EDAC_SECDED;301		break;302	default:303		edac_dbg(0, "Unknown/reserved ECC state in NBXCFG register!\n");304		edac_mode = EDAC_UNKNOWN;305		break;306	}307 308	i82443bxgx_init_csrows(mci, pdev, edac_mode, mtype);309 310	/* Many BIOSes don't clear error flags on boot, so do this311	 * here, or we get "phantom" errors occurring at module-load312	 * time. */313	pci_write_bits32(pdev, I82443BXGX_EAP,314			(I82443BXGX_EAP_OFFSET_SBE |315				I82443BXGX_EAP_OFFSET_MBE),316			(I82443BXGX_EAP_OFFSET_SBE |317				I82443BXGX_EAP_OFFSET_MBE));318 319	mci->mod_name = EDAC_MOD_STR;320	mci->ctl_name = "I82443BXGX";321	mci->dev_name = pci_name(pdev);322	mci->edac_check = i82443bxgx_edacmc_check;323	mci->ctl_page_to_phys = NULL;324 325	if (edac_mc_add_mc(mci)) {326		edac_dbg(3, "failed edac_mc_add_mc()\n");327		goto fail;328	}329 330	/* allocating generic PCI control info */331	i82443bxgx_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);332	if (!i82443bxgx_pci) {333		printk(KERN_WARNING334			"%s(): Unable to create PCI control\n",335			__func__);336		printk(KERN_WARNING337			"%s(): PCI error report via EDAC not setup\n",338			__func__);339	}340 341	edac_dbg(3, "MC: success\n");342	return 0;343 344fail:345	edac_mc_free(mci);346	return -ENODEV;347}348 349/* returns count (>= 0), or negative on error */350static int i82443bxgx_edacmc_init_one(struct pci_dev *pdev,351				      const struct pci_device_id *ent)352{353	int rc;354 355	edac_dbg(0, "MC:\n");356 357	/* don't need to call pci_enable_device() */358	rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data);359 360	if (mci_pdev == NULL)361		mci_pdev = pci_dev_get(pdev);362 363	return rc;364}365 366static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)367{368	struct mem_ctl_info *mci;369 370	edac_dbg(0, "\n");371 372	if (i82443bxgx_pci)373		edac_pci_release_generic_ctl(i82443bxgx_pci);374 375	if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)376		return;377 378	edac_mc_free(mci);379}380 381static const struct pci_device_id i82443bxgx_pci_tbl[] = {382	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)},383	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)},384	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0)},385	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2)},386	{0,}			/* 0 terminated list. */387};388 389MODULE_DEVICE_TABLE(pci, i82443bxgx_pci_tbl);390 391static struct pci_driver i82443bxgx_edacmc_driver = {392	.name = EDAC_MOD_STR,393	.probe = i82443bxgx_edacmc_init_one,394	.remove = i82443bxgx_edacmc_remove_one,395	.id_table = i82443bxgx_pci_tbl,396};397 398static int __init i82443bxgx_edacmc_init(void)399{400	int pci_rc;401       /* Ensure that the OPSTATE is set correctly for POLL or NMI */402       opstate_init();403 404	pci_rc = pci_register_driver(&i82443bxgx_edacmc_driver);405	if (pci_rc < 0)406		goto fail0;407 408	if (mci_pdev == NULL) {409		const struct pci_device_id *id = &i82443bxgx_pci_tbl[0];410		int i = 0;411		i82443bxgx_registered = 0;412 413		while (mci_pdev == NULL && id->vendor != 0) {414			mci_pdev = pci_get_device(id->vendor,415					id->device, NULL);416			i++;417			id = &i82443bxgx_pci_tbl[i];418		}419		if (!mci_pdev) {420			edac_dbg(0, "i82443bxgx pci_get_device fail\n");421			pci_rc = -ENODEV;422			goto fail1;423		}424 425		pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl);426 427		if (pci_rc < 0) {428			edac_dbg(0, "i82443bxgx init fail\n");429			pci_rc = -ENODEV;430			goto fail1;431		}432	}433 434	return 0;435 436fail1:437	pci_unregister_driver(&i82443bxgx_edacmc_driver);438 439fail0:440	pci_dev_put(mci_pdev);441	return pci_rc;442}443 444static void __exit i82443bxgx_edacmc_exit(void)445{446	pci_unregister_driver(&i82443bxgx_edacmc_driver);447 448	if (!i82443bxgx_registered)449		i82443bxgx_edacmc_remove_one(mci_pdev);450 451	pci_dev_put(mci_pdev);452}453 454module_init(i82443bxgx_edacmc_init);455module_exit(i82443bxgx_edacmc_exit);456 457MODULE_LICENSE("GPL");458MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD");459MODULE_DESCRIPTION("EDAC MC support for Intel 82443BX/GX memory controllers");460 461module_param(edac_op_state, int, 0444);462MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");463