12f768af7SAlan Cox /*
22f768af7SAlan Cox * Radisys 82600 Embedded chipset Memory Controller kernel module
32f768af7SAlan Cox * (C) 2005 EADS Astrium
42f768af7SAlan Cox * This file may be distributed under the terms of the
52f768af7SAlan Cox * GNU General Public License.
62f768af7SAlan Cox *
72f768af7SAlan Cox * Written by Tim Small <tim@buttersideup.com>, based on work by Thayne
82f768af7SAlan Cox * Harbaugh, Dan Hollis <goemon at anime dot net> and others.
92f768af7SAlan Cox *
102f768af7SAlan Cox * $Id: edac_r82600.c,v 1.1.2.6 2005/10/05 00:43:44 dsp_llnl Exp $
112f768af7SAlan Cox *
122f768af7SAlan Cox * Written with reference to 82600 High Integration Dual PCI System
132f768af7SAlan Cox * Controller Data Book:
14c4192705SDave Jiang * www.radisys.com/files/support_downloads/007-01277-0002.82600DataBook.pdf
152f768af7SAlan Cox * references to this document given in []
162f768af7SAlan Cox */
172f768af7SAlan Cox
182f768af7SAlan Cox #include <linux/module.h>
192f768af7SAlan Cox #include <linux/init.h>
202f768af7SAlan Cox #include <linux/pci.h>
212f768af7SAlan Cox #include <linux/pci_ids.h>
22c3c52bceSHitoshi Mitake #include <linux/edac.h>
2378d88e8aSMauro Carvalho Chehab #include "edac_module.h"
242f768af7SAlan Cox
25929a40ecSDoug Thompson #define EDAC_MOD_STR "r82600_edac"
2637f04581SDoug Thompson
27537fba28SDave Peterson #define r82600_printk(level, fmt, arg...) \
28537fba28SDave Peterson edac_printk(level, "r82600", fmt, ##arg)
29537fba28SDave Peterson
30537fba28SDave Peterson #define r82600_mc_printk(mci, level, fmt, arg...) \
31537fba28SDave Peterson edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg)
32537fba28SDave Peterson
332f768af7SAlan Cox /* Radisys say "The 82600 integrates a main memory SDRAM controller that
342f768af7SAlan Cox * supports up to four banks of memory. The four banks can support a mix of
352f768af7SAlan Cox * sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs,
362f768af7SAlan Cox * each of which can be any size from 16MB to 512MB. Both registered (control
372f768af7SAlan Cox * signals buffered) and unbuffered DIMM types are supported. Mixing of
382f768af7SAlan Cox * registered and unbuffered DIMMs as well as mixing of ECC and non-ECC DIMMs
392f768af7SAlan Cox * is not allowed. The 82600 SDRAM interface operates at the same frequency as
402f768af7SAlan Cox * the CPU bus, 66MHz, 100MHz or 133MHz."
412f768af7SAlan Cox */
422f768af7SAlan Cox
432f768af7SAlan Cox #define R82600_NR_CSROWS 4
442f768af7SAlan Cox #define R82600_NR_CHANS 1
452f768af7SAlan Cox #define R82600_NR_DIMMS 4
462f768af7SAlan Cox
472f768af7SAlan Cox #define R82600_BRIDGE_ID 0x8200
482f768af7SAlan Cox
492f768af7SAlan Cox /* Radisys 82600 register addresses - device 0 function 0 - PCI bridge */
502f768af7SAlan Cox #define R82600_DRAMC 0x57 /* Various SDRAM related control bits
512f768af7SAlan Cox * all bits are R/W
522f768af7SAlan Cox *
532f768af7SAlan Cox * 7 SDRAM ISA Hole Enable
542f768af7SAlan Cox * 6 Flash Page Mode Enable
552f768af7SAlan Cox * 5 ECC Enable: 1=ECC 0=noECC
562f768af7SAlan Cox * 4 DRAM DIMM Type: 1=
572f768af7SAlan Cox * 3 BIOS Alias Disable
582f768af7SAlan Cox * 2 SDRAM BIOS Flash Write Enable
592f768af7SAlan Cox * 1:0 SDRAM Refresh Rate: 00=Disabled
602f768af7SAlan Cox * 01=7.8usec (256Mbit SDRAMs)
612f768af7SAlan Cox * 10=15.6us 11=125usec
622f768af7SAlan Cox */
632f768af7SAlan Cox
642f768af7SAlan Cox #define R82600_SDRAMC 0x76 /* "SDRAM Control Register"
652f768af7SAlan Cox * More SDRAM related control bits
662f768af7SAlan Cox * all bits are R/W
672f768af7SAlan Cox *
682f768af7SAlan Cox * 15:8 Reserved.
692f768af7SAlan Cox *
702f768af7SAlan Cox * 7:5 Special SDRAM Mode Select
712f768af7SAlan Cox *
722f768af7SAlan Cox * 4 Force ECC
732f768af7SAlan Cox *
742f768af7SAlan Cox * 1=Drive ECC bits to 0 during
752f768af7SAlan Cox * write cycles (i.e. ECC test mode)
762f768af7SAlan Cox *
772f768af7SAlan Cox * 0=Normal ECC functioning
782f768af7SAlan Cox *
792f768af7SAlan Cox * 3 Enhanced Paging Enable
802f768af7SAlan Cox *
812f768af7SAlan Cox * 2 CAS# Latency 0=3clks 1=2clks
822f768af7SAlan Cox *
832f768af7SAlan Cox * 1 RAS# to CAS# Delay 0=3 1=2
842f768af7SAlan Cox *
852f768af7SAlan Cox * 0 RAS# Precharge 0=3 1=2
862f768af7SAlan Cox */
872f768af7SAlan Cox
882f768af7SAlan Cox #define R82600_EAP 0x80 /* ECC Error Address Pointer Register
892f768af7SAlan Cox *
902f768af7SAlan Cox * 31 Disable Hardware Scrubbing (RW)
912f768af7SAlan Cox * 0=Scrub on corrected read
922f768af7SAlan Cox * 1=Don't scrub on corrected read
932f768af7SAlan Cox *
942f768af7SAlan Cox * 30:12 Error Address Pointer (RO)
952f768af7SAlan Cox * Upper 19 bits of error address
962f768af7SAlan Cox *
972f768af7SAlan Cox * 11:4 Syndrome Bits (RO)
982f768af7SAlan Cox *
992f768af7SAlan Cox * 3 BSERR# on multibit error (RW)
1002f768af7SAlan Cox * 1=enable 0=disable
1012f768af7SAlan Cox *
1022f768af7SAlan Cox * 2 NMI on Single Bit Eror (RW)
1032f768af7SAlan Cox * 1=NMI triggered by SBE n.b. other
1042f768af7SAlan Cox * prerequeists
1052f768af7SAlan Cox * 0=NMI not triggered
1062f768af7SAlan Cox *
1072f768af7SAlan Cox * 1 MBE (R/WC)
1082f768af7SAlan Cox * read 1=MBE at EAP (see above)
1092f768af7SAlan Cox * read 0=no MBE, or SBE occurred first
1102f768af7SAlan Cox * write 1=Clear MBE status (must also
1112f768af7SAlan Cox * clear SBE)
1122f768af7SAlan Cox * write 0=NOP
1132f768af7SAlan Cox *
1142f768af7SAlan Cox * 1 SBE (R/WC)
1152f768af7SAlan Cox * read 1=SBE at EAP (see above)
1162f768af7SAlan Cox * read 0=no SBE, or MBE occurred first
1172f768af7SAlan Cox * write 1=Clear SBE status (must also
1182f768af7SAlan Cox * clear MBE)
1192f768af7SAlan Cox * write 0=NOP
1202f768af7SAlan Cox */
1212f768af7SAlan Cox
12225985edcSLucas De Marchi #define R82600_DRBA 0x60 /* + 0x60..0x63 SDRAM Row Boundary Address
1232f768af7SAlan Cox * Registers
1242f768af7SAlan Cox *
1252f768af7SAlan Cox * 7:0 Address lines 30:24 - upper limit of
1262f768af7SAlan Cox * each row [p57]
1272f768af7SAlan Cox */
1282f768af7SAlan Cox
1292f768af7SAlan Cox struct r82600_error_info {
1302f768af7SAlan Cox u32 eapr;
1312f768af7SAlan Cox };
1322f768af7SAlan Cox
13390ab5ee9SRusty Russell static bool disable_hardware_scrub;
1342f768af7SAlan Cox
135456a2f95SDave Jiang static struct edac_pci_ctl_info *r82600_pci;
136456a2f95SDave Jiang
r82600_get_error_info(struct mem_ctl_info * mci,struct r82600_error_info * info)1372f768af7SAlan Cox static void r82600_get_error_info(struct mem_ctl_info *mci,
1382f768af7SAlan Cox struct r82600_error_info *info)
1392f768af7SAlan Cox {
14037f04581SDoug Thompson struct pci_dev *pdev;
14137f04581SDoug Thompson
142fd687502SMauro Carvalho Chehab pdev = to_pci_dev(mci->pdev);
14337f04581SDoug Thompson pci_read_config_dword(pdev, R82600_EAP, &info->eapr);
1442f768af7SAlan Cox
1452f768af7SAlan Cox if (info->eapr & BIT(0))
1462f768af7SAlan Cox /* Clear error to allow next error to be reported [p.62] */
14737f04581SDoug Thompson pci_write_bits32(pdev, R82600_EAP,
1482f768af7SAlan Cox ((u32) BIT(0) & (u32) BIT(1)),
1492f768af7SAlan Cox ((u32) BIT(0) & (u32) BIT(1)));
1502f768af7SAlan Cox
1512f768af7SAlan Cox if (info->eapr & BIT(1))
1522f768af7SAlan Cox /* Clear error to allow next error to be reported [p.62] */
15337f04581SDoug Thompson pci_write_bits32(pdev, R82600_EAP,
1542f768af7SAlan Cox ((u32) BIT(0) & (u32) BIT(1)),
1552f768af7SAlan Cox ((u32) BIT(0) & (u32) BIT(1)));
1562f768af7SAlan Cox }
1572f768af7SAlan Cox
r82600_process_error_info(struct mem_ctl_info * mci,struct r82600_error_info * info,int handle_errors)1582f768af7SAlan Cox static int r82600_process_error_info(struct mem_ctl_info *mci,
159cddbfcacSDouglas Thompson struct r82600_error_info *info,
160cddbfcacSDouglas Thompson int handle_errors)
1612f768af7SAlan Cox {
1622f768af7SAlan Cox int error_found;
1632f768af7SAlan Cox u32 eapaddr, page;
1642f768af7SAlan Cox u32 syndrome;
1652f768af7SAlan Cox
1662f768af7SAlan Cox error_found = 0;
1672f768af7SAlan Cox
1682f768af7SAlan Cox /* bits 30:12 store the upper 19 bits of the 32 bit error address */
1692f768af7SAlan Cox eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13;
1702f768af7SAlan Cox /* Syndrome in bits 11:4 [p.62] */
1712f768af7SAlan Cox syndrome = (info->eapr >> 4) & 0xFF;
1722f768af7SAlan Cox
1732f768af7SAlan Cox /* the R82600 reports at less than page *
1742f768af7SAlan Cox * granularity (upper 19 bits only) */
1752f768af7SAlan Cox page = eapaddr >> PAGE_SHIFT;
1762f768af7SAlan Cox
1772f768af7SAlan Cox if (info->eapr & BIT(0)) { /* CE? */
1782f768af7SAlan Cox error_found = 1;
1792f768af7SAlan Cox
1802f768af7SAlan Cox if (handle_errors)
1819eb07a7fSMauro Carvalho Chehab edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
18263b5d1d9SMauro Carvalho Chehab page, 0, syndrome,
183052dfb45SDouglas Thompson edac_mc_find_csrow_by_page(mci, page),
18463b5d1d9SMauro Carvalho Chehab 0, -1,
18503f7eae8SMauro Carvalho Chehab mci->ctl_name, "");
1862f768af7SAlan Cox }
1872f768af7SAlan Cox
1882f768af7SAlan Cox if (info->eapr & BIT(1)) { /* UE? */
1892f768af7SAlan Cox error_found = 1;
1902f768af7SAlan Cox
1912f768af7SAlan Cox if (handle_errors)
1922f768af7SAlan Cox /* 82600 doesn't give enough info */
1939eb07a7fSMauro Carvalho Chehab edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
19463b5d1d9SMauro Carvalho Chehab page, 0, 0,
1952f768af7SAlan Cox edac_mc_find_csrow_by_page(mci, page),
19663b5d1d9SMauro Carvalho Chehab 0, -1,
19703f7eae8SMauro Carvalho Chehab mci->ctl_name, "");
1982f768af7SAlan Cox }
1992f768af7SAlan Cox
2002f768af7SAlan Cox return error_found;
2012f768af7SAlan Cox }
2022f768af7SAlan Cox
r82600_check(struct mem_ctl_info * mci)2032f768af7SAlan Cox static void r82600_check(struct mem_ctl_info *mci)
2042f768af7SAlan Cox {
2052f768af7SAlan Cox struct r82600_error_info info;
2062f768af7SAlan Cox
2072f768af7SAlan Cox r82600_get_error_info(mci, &info);
2082f768af7SAlan Cox r82600_process_error_info(mci, &info, 1);
2092f768af7SAlan Cox }
2102f768af7SAlan Cox
ecc_enabled(u8 dramcr)21113189525SDoug Thompson static inline int ecc_enabled(u8 dramcr)
21213189525SDoug Thompson {
21313189525SDoug Thompson return dramcr & BIT(5);
21413189525SDoug Thompson }
21513189525SDoug Thompson
r82600_init_csrows(struct mem_ctl_info * mci,struct pci_dev * pdev,u8 dramcr)21613189525SDoug Thompson static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
21713189525SDoug Thompson u8 dramcr)
21813189525SDoug Thompson {
21913189525SDoug Thompson struct csrow_info *csrow;
220084a4fccSMauro Carvalho Chehab struct dimm_info *dimm;
22113189525SDoug Thompson int index;
22225985edcSLucas De Marchi u8 drbar; /* SDRAM Row Boundary Address Register */
22313189525SDoug Thompson u32 row_high_limit, row_high_limit_last;
22413189525SDoug Thompson u32 reg_sdram, ecc_on, row_base;
22513189525SDoug Thompson
22613189525SDoug Thompson ecc_on = ecc_enabled(dramcr);
22713189525SDoug Thompson reg_sdram = dramcr & BIT(4);
22813189525SDoug Thompson row_high_limit_last = 0;
22913189525SDoug Thompson
23013189525SDoug Thompson for (index = 0; index < mci->nr_csrows; index++) {
231de3910ebSMauro Carvalho Chehab csrow = mci->csrows[index];
232de3910ebSMauro Carvalho Chehab dimm = csrow->channels[0]->dimm;
23313189525SDoug Thompson
23413189525SDoug Thompson /* find the DRAM Chip Select Base address and mask */
23513189525SDoug Thompson pci_read_config_byte(pdev, R82600_DRBA + index, &drbar);
23613189525SDoug Thompson
237956b9ba1SJoe Perches edac_dbg(1, "Row=%d DRBA = %#0x\n", index, drbar);
23813189525SDoug Thompson
23913189525SDoug Thompson row_high_limit = ((u32) drbar << 24);
24013189525SDoug Thompson /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */
24113189525SDoug Thompson
242956b9ba1SJoe Perches edac_dbg(1, "Row=%d, Boundary Address=%#0x, Last = %#0x\n",
243dd23cd6eSMauro Carvalho Chehab index, row_high_limit, row_high_limit_last);
24413189525SDoug Thompson
24513189525SDoug Thompson /* Empty row [p.57] */
24613189525SDoug Thompson if (row_high_limit == row_high_limit_last)
24713189525SDoug Thompson continue;
24813189525SDoug Thompson
24913189525SDoug Thompson row_base = row_high_limit_last;
25013189525SDoug Thompson
25113189525SDoug Thompson csrow->first_page = row_base >> PAGE_SHIFT;
25213189525SDoug Thompson csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
253a895bf8bSMauro Carvalho Chehab
254a895bf8bSMauro Carvalho Chehab dimm->nr_pages = csrow->last_page - csrow->first_page + 1;
25513189525SDoug Thompson /* Error address is top 19 bits - so granularity is *
25613189525SDoug Thompson * 14 bits */
257084a4fccSMauro Carvalho Chehab dimm->grain = 1 << 14;
258084a4fccSMauro Carvalho Chehab dimm->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
25913189525SDoug Thompson /* FIXME - check that this is unknowable with this chipset */
260084a4fccSMauro Carvalho Chehab dimm->dtype = DEV_UNKNOWN;
26113189525SDoug Thompson
26213189525SDoug Thompson /* Mode is global on 82600 */
263084a4fccSMauro Carvalho Chehab dimm->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
26413189525SDoug Thompson row_high_limit_last = row_high_limit;
26513189525SDoug Thompson }
26613189525SDoug Thompson }
26713189525SDoug Thompson
r82600_probe1(struct pci_dev * pdev,int dev_idx)2682f768af7SAlan Cox static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
2692f768af7SAlan Cox {
27013189525SDoug Thompson struct mem_ctl_info *mci;
27163b5d1d9SMauro Carvalho Chehab struct edac_mc_layer layers[2];
2722f768af7SAlan Cox u8 dramcr;
2732f768af7SAlan Cox u32 eapr;
2742f768af7SAlan Cox u32 scrub_disabled;
2752f768af7SAlan Cox u32 sdram_refresh_rate;
276749ede57SDave Peterson struct r82600_error_info discard;
2772f768af7SAlan Cox
278956b9ba1SJoe Perches edac_dbg(0, "\n");
2792f768af7SAlan Cox pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
2802f768af7SAlan Cox pci_read_config_dword(pdev, R82600_EAP, &eapr);
2812f768af7SAlan Cox scrub_disabled = eapr & BIT(31);
2822f768af7SAlan Cox sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
283956b9ba1SJoe Perches edac_dbg(2, "sdram refresh rate = %#0x\n", sdram_refresh_rate);
284956b9ba1SJoe Perches edac_dbg(2, "DRAMC register = %#0x\n", dramcr);
28563b5d1d9SMauro Carvalho Chehab layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
28663b5d1d9SMauro Carvalho Chehab layers[0].size = R82600_NR_CSROWS;
28763b5d1d9SMauro Carvalho Chehab layers[0].is_virt_csrow = true;
28863b5d1d9SMauro Carvalho Chehab layers[1].type = EDAC_MC_LAYER_CHANNEL;
28963b5d1d9SMauro Carvalho Chehab layers[1].size = R82600_NR_CHANS;
29063b5d1d9SMauro Carvalho Chehab layers[1].is_virt_csrow = false;
291ca0907b9SMauro Carvalho Chehab mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
29213189525SDoug Thompson if (mci == NULL)
29313189525SDoug Thompson return -ENOMEM;
2942f768af7SAlan Cox
295956b9ba1SJoe Perches edac_dbg(0, "mci = %p\n", mci);
296fd687502SMauro Carvalho Chehab mci->pdev = &pdev->dev;
2972f768af7SAlan Cox mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
2982f768af7SAlan Cox mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
299e7ecd891SDave Peterson /* FIXME try to work out if the chip leads have been used for COM2
300e7ecd891SDave Peterson * instead on this board? [MA6?] MAYBE:
301e7ecd891SDave Peterson */
3022f768af7SAlan Cox
3032f768af7SAlan Cox /* On the R82600, the pins for memory bits 72:65 - i.e. the *
3042f768af7SAlan Cox * EC bits are shared with the pins for COM2 (!), so if COM2 *
3052f768af7SAlan Cox * is enabled, we assume COM2 is wired up, and thus no EDAC *
3062f768af7SAlan Cox * is possible. */
3072f768af7SAlan Cox mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
308e7ecd891SDave Peterson
30913189525SDoug Thompson if (ecc_enabled(dramcr)) {
3102f768af7SAlan Cox if (scrub_disabled)
311956b9ba1SJoe Perches edac_dbg(3, "mci = %p - Scrubbing disabled! EAP: %#0x\n",
312956b9ba1SJoe Perches mci, eapr);
3132f768af7SAlan Cox } else
3142f768af7SAlan Cox mci->edac_cap = EDAC_FLAG_NONE;
3152f768af7SAlan Cox
316680cbbbbSDave Peterson mci->mod_name = EDAC_MOD_STR;
3172f768af7SAlan Cox mci->ctl_name = "R82600";
318c4192705SDave Jiang mci->dev_name = pci_name(pdev);
3192f768af7SAlan Cox mci->edac_check = r82600_check;
3202f768af7SAlan Cox mci->ctl_page_to_phys = NULL;
32113189525SDoug Thompson r82600_init_csrows(mci, pdev, dramcr);
322749ede57SDave Peterson r82600_get_error_info(mci, &discard); /* clear counters */
3232f768af7SAlan Cox
3242d7bbb91SDoug Thompson /* Here we assume that we will never see multiple instances of this
3252d7bbb91SDoug Thompson * type of memory controller. The ID is therefore hardcoded to 0.
3262d7bbb91SDoug Thompson */
327b8f6f975SDoug Thompson if (edac_mc_add_mc(mci)) {
328956b9ba1SJoe Perches edac_dbg(3, "failed edac_mc_add_mc()\n");
3292f768af7SAlan Cox goto fail;
3302f768af7SAlan Cox }
3312f768af7SAlan Cox
3322f768af7SAlan Cox /* get this far and it's successful */
3332f768af7SAlan Cox
3342f768af7SAlan Cox if (disable_hardware_scrub) {
335956b9ba1SJoe Perches edac_dbg(3, "Disabling Hardware Scrub (scrub on error)\n");
33637f04581SDoug Thompson pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31));
3372f768af7SAlan Cox }
3382f768af7SAlan Cox
339456a2f95SDave Jiang /* allocating generic PCI control info */
340456a2f95SDave Jiang r82600_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
341456a2f95SDave Jiang if (!r82600_pci) {
342456a2f95SDave Jiang printk(KERN_WARNING
343456a2f95SDave Jiang "%s(): Unable to create PCI control\n",
344456a2f95SDave Jiang __func__);
345456a2f95SDave Jiang printk(KERN_WARNING
346456a2f95SDave Jiang "%s(): PCI error report via EDAC not setup\n",
347456a2f95SDave Jiang __func__);
348456a2f95SDave Jiang }
349456a2f95SDave Jiang
350956b9ba1SJoe Perches edac_dbg(3, "success\n");
3512f768af7SAlan Cox return 0;
3522f768af7SAlan Cox
3532f768af7SAlan Cox fail:
3542f768af7SAlan Cox edac_mc_free(mci);
35513189525SDoug Thompson return -ENODEV;
3562f768af7SAlan Cox }
3572f768af7SAlan Cox
3582f768af7SAlan Cox /* returns count (>= 0), or negative on error */
r82600_init_one(struct pci_dev * pdev,const struct pci_device_id * ent)3599b3c6e85SGreg Kroah-Hartman static int r82600_init_one(struct pci_dev *pdev,
3602f768af7SAlan Cox const struct pci_device_id *ent)
3612f768af7SAlan Cox {
362956b9ba1SJoe Perches edac_dbg(0, "\n");
3632f768af7SAlan Cox
364ee6583f6SRoman Fietze /* don't need to call pci_enable_device() */
3652f768af7SAlan Cox return r82600_probe1(pdev, ent->driver_data);
3662f768af7SAlan Cox }
3672f768af7SAlan Cox
r82600_remove_one(struct pci_dev * pdev)3689b3c6e85SGreg Kroah-Hartman static void r82600_remove_one(struct pci_dev *pdev)
3692f768af7SAlan Cox {
3702f768af7SAlan Cox struct mem_ctl_info *mci;
3712f768af7SAlan Cox
372956b9ba1SJoe Perches edac_dbg(0, "\n");
3732f768af7SAlan Cox
374456a2f95SDave Jiang if (r82600_pci)
375456a2f95SDave Jiang edac_pci_release_generic_ctl(r82600_pci);
376456a2f95SDave Jiang
37737f04581SDoug Thompson if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
37818dbc337SDave Peterson return;
37918dbc337SDave Peterson
3802f768af7SAlan Cox edac_mc_free(mci);
3812f768af7SAlan Cox }
3822f768af7SAlan Cox
383ba935f40SJingoo Han static const struct pci_device_id r82600_pci_tbl[] = {
384e7ecd891SDave Peterson {
385e7ecd891SDave Peterson PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)
386e7ecd891SDave Peterson },
387e7ecd891SDave Peterson {
388e7ecd891SDave Peterson 0,
389e7ecd891SDave Peterson } /* 0 terminated list. */
3902f768af7SAlan Cox };
3912f768af7SAlan Cox
3922f768af7SAlan Cox MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
3932f768af7SAlan Cox
3942f768af7SAlan Cox static struct pci_driver r82600_driver = {
395680cbbbbSDave Peterson .name = EDAC_MOD_STR,
3962f768af7SAlan Cox .probe = r82600_init_one,
3979b3c6e85SGreg Kroah-Hartman .remove = r82600_remove_one,
3982f768af7SAlan Cox .id_table = r82600_pci_tbl,
3992f768af7SAlan Cox };
4002f768af7SAlan Cox
r82600_init(void)401da9bb1d2SAlan Cox static int __init r82600_init(void)
4022f768af7SAlan Cox {
403c3c52bceSHitoshi Mitake /* Ensure that the OPSTATE is set correctly for POLL or NMI */
404c3c52bceSHitoshi Mitake opstate_init();
405c3c52bceSHitoshi Mitake
4062f768af7SAlan Cox return pci_register_driver(&r82600_driver);
4072f768af7SAlan Cox }
4082f768af7SAlan Cox
r82600_exit(void)4092f768af7SAlan Cox static void __exit r82600_exit(void)
4102f768af7SAlan Cox {
4112f768af7SAlan Cox pci_unregister_driver(&r82600_driver);
4122f768af7SAlan Cox }
4132f768af7SAlan Cox
4142f768af7SAlan Cox module_init(r82600_init);
4152f768af7SAlan Cox module_exit(r82600_exit);
4162f768af7SAlan Cox
4172f768af7SAlan Cox MODULE_LICENSE("GPL");
418*371b27f2SBorislav Petkov (AMD) MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. on behalf of EADS Astrium");
4192f768af7SAlan Cox MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
4202f768af7SAlan Cox
4212f768af7SAlan Cox module_param(disable_hardware_scrub, bool, 0644);
4222f768af7SAlan Cox MODULE_PARM_DESC(disable_hardware_scrub,
4232f768af7SAlan Cox "If set, disable the chipset's automatic scrub for CEs");
424c3c52bceSHitoshi Mitake
425c3c52bceSHitoshi Mitake module_param(edac_op_state, int, 0444);
426c3c52bceSHitoshi Mitake MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
427