Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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