Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * AMD 76x Memory Controller kernel module
0003  * (C) 2003 Linux Networx (http://lnxi.com)
0004  * This file may be distributed under the terms of the
0005  * GNU General Public License.
0006  *
0007  * Written by Thayne Harbaugh
0008  * Based on work by Dan Hollis <goemon at anime dot net> and others.
0009  *  http://www.anime.net/~goemon/linux-ecc/
0010  *
0011  * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $
0012  *
0013  */
0014 
0015 #include <linux/module.h>
0016 #include <linux/init.h>
0017 #include <linux/pci.h>
0018 #include <linux/pci_ids.h>
0019 #include <linux/edac.h>
0020 #include "edac_module.h"
0021 
0022 #define EDAC_MOD_STR    "amd76x_edac"
0023 
0024 #define amd76x_printk(level, fmt, arg...) \
0025     edac_printk(level, "amd76x", fmt, ##arg)
0026 
0027 #define amd76x_mc_printk(mci, level, fmt, arg...) \
0028     edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg)
0029 
0030 #define AMD76X_NR_CSROWS 8
0031 #define AMD76X_NR_DIMMS  4
0032 
0033 /* AMD 76x register addresses - device 0 function 0 - PCI bridge */
0034 
0035 #define AMD76X_ECC_MODE_STATUS  0x48    /* Mode and status of ECC (32b)
0036                      *
0037                      * 31:16 reserved
0038                      * 15:14 SERR enabled: x1=ue 1x=ce
0039                      * 13    reserved
0040                      * 12    diag: disabled, enabled
0041                      * 11:10 mode: dis, EC, ECC, ECC+scrub
0042                      *  9:8  status: x1=ue 1x=ce
0043                      *  7:4  UE cs row
0044                      *  3:0  CE cs row
0045                      */
0046 
0047 #define AMD76X_DRAM_MODE_STATUS 0x58    /* DRAM Mode and status (32b)
0048                      *
0049                      * 31:26 clock disable 5 - 0
0050                      * 25    SDRAM init
0051                      * 24    reserved
0052                      * 23    mode register service
0053                      * 22:21 suspend to RAM
0054                      * 20    burst refresh enable
0055                      * 19    refresh disable
0056                      * 18    reserved
0057                      * 17:16 cycles-per-refresh
0058                      * 15:8  reserved
0059                      *  7:0  x4 mode enable 7 - 0
0060                      */
0061 
0062 #define AMD76X_MEM_BASE_ADDR    0xC0    /* Memory base address (8 x 32b)
0063                      *
0064                      * 31:23 chip-select base
0065                      * 22:16 reserved
0066                      * 15:7  chip-select mask
0067                      *  6:3  reserved
0068                      *  2:1  address mode
0069                      *  0    chip-select enable
0070                      */
0071 
0072 struct amd76x_error_info {
0073     u32 ecc_mode_status;
0074 };
0075 
0076 enum amd76x_chips {
0077     AMD761 = 0,
0078     AMD762
0079 };
0080 
0081 struct amd76x_dev_info {
0082     const char *ctl_name;
0083 };
0084 
0085 static const struct amd76x_dev_info amd76x_devs[] = {
0086     [AMD761] = {
0087         .ctl_name = "AMD761"},
0088     [AMD762] = {
0089         .ctl_name = "AMD762"},
0090 };
0091 
0092 static struct edac_pci_ctl_info *amd76x_pci;
0093 
0094 /**
0095  *  amd76x_get_error_info   -   fetch error information
0096  *  @mci: Memory controller
0097  *  @info: Info to fill in
0098  *
0099  *  Fetch and store the AMD76x ECC status. Clear pending status
0100  *  on the chip so that further errors will be reported
0101  */
0102 static void amd76x_get_error_info(struct mem_ctl_info *mci,
0103                 struct amd76x_error_info *info)
0104 {
0105     struct pci_dev *pdev;
0106 
0107     pdev = to_pci_dev(mci->pdev);
0108     pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS,
0109             &info->ecc_mode_status);
0110 
0111     if (info->ecc_mode_status & BIT(8))
0112         pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
0113                  (u32) BIT(8), (u32) BIT(8));
0114 
0115     if (info->ecc_mode_status & BIT(9))
0116         pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
0117                  (u32) BIT(9), (u32) BIT(9));
0118 }
0119 
0120 /**
0121  *  amd76x_process_error_info   -   Error check
0122  *  @mci: Memory controller
0123  *  @info: Previously fetched information from chip
0124  *  @handle_errors: 1 if we should do recovery
0125  *
0126  *  Process the chip state and decide if an error has occurred.
0127  *  A return of 1 indicates an error. Also if handle_errors is true
0128  *  then attempt to handle and clean up after the error
0129  */
0130 static int amd76x_process_error_info(struct mem_ctl_info *mci,
0131                 struct amd76x_error_info *info,
0132                 int handle_errors)
0133 {
0134     int error_found;
0135     u32 row;
0136 
0137     error_found = 0;
0138 
0139     /*
0140      *      Check for an uncorrectable error
0141      */
0142     if (info->ecc_mode_status & BIT(8)) {
0143         error_found = 1;
0144 
0145         if (handle_errors) {
0146             row = (info->ecc_mode_status >> 4) & 0xf;
0147             edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
0148                          mci->csrows[row]->first_page, 0, 0,
0149                          row, 0, -1,
0150                          mci->ctl_name, "");
0151         }
0152     }
0153 
0154     /*
0155      *      Check for a correctable error
0156      */
0157     if (info->ecc_mode_status & BIT(9)) {
0158         error_found = 1;
0159 
0160         if (handle_errors) {
0161             row = info->ecc_mode_status & 0xf;
0162             edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
0163                          mci->csrows[row]->first_page, 0, 0,
0164                          row, 0, -1,
0165                          mci->ctl_name, "");
0166         }
0167     }
0168 
0169     return error_found;
0170 }
0171 
0172 /**
0173  *  amd76x_check    -   Poll the controller
0174  *  @mci: Memory controller
0175  *
0176  *  Called by the poll handlers this function reads the status
0177  *  from the controller and checks for errors.
0178  */
0179 static void amd76x_check(struct mem_ctl_info *mci)
0180 {
0181     struct amd76x_error_info info;
0182     amd76x_get_error_info(mci, &info);
0183     amd76x_process_error_info(mci, &info, 1);
0184 }
0185 
0186 static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
0187             enum edac_type edac_mode)
0188 {
0189     struct csrow_info *csrow;
0190     struct dimm_info *dimm;
0191     u32 mba, mba_base, mba_mask, dms;
0192     int index;
0193 
0194     for (index = 0; index < mci->nr_csrows; index++) {
0195         csrow = mci->csrows[index];
0196         dimm = csrow->channels[0]->dimm;
0197 
0198         /* find the DRAM Chip Select Base address and mask */
0199         pci_read_config_dword(pdev,
0200                 AMD76X_MEM_BASE_ADDR + (index * 4), &mba);
0201 
0202         if (!(mba & BIT(0)))
0203             continue;
0204 
0205         mba_base = mba & 0xff800000UL;
0206         mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
0207         pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms);
0208         csrow->first_page = mba_base >> PAGE_SHIFT;
0209         dimm->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
0210         csrow->last_page = csrow->first_page + dimm->nr_pages - 1;
0211         csrow->page_mask = mba_mask >> PAGE_SHIFT;
0212         dimm->grain = dimm->nr_pages << PAGE_SHIFT;
0213         dimm->mtype = MEM_RDDR;
0214         dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
0215         dimm->edac_mode = edac_mode;
0216     }
0217 }
0218 
0219 /**
0220  *  amd76x_probe1   -   Perform set up for detected device
0221  *  @pdev; PCI device detected
0222  *  @dev_idx: Device type index
0223  *
0224  *  We have found an AMD76x and now need to set up the memory
0225  *  controller status reporting. We configure and set up the
0226  *  memory controller reporting and claim the device.
0227  */
0228 static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
0229 {
0230     static const enum edac_type ems_modes[] = {
0231         EDAC_NONE,
0232         EDAC_EC,
0233         EDAC_SECDED,
0234         EDAC_SECDED
0235     };
0236     struct mem_ctl_info *mci;
0237     struct edac_mc_layer layers[2];
0238     u32 ems;
0239     u32 ems_mode;
0240     struct amd76x_error_info discard;
0241 
0242     edac_dbg(0, "\n");
0243     pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
0244     ems_mode = (ems >> 10) & 0x3;
0245 
0246     layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
0247     layers[0].size = AMD76X_NR_CSROWS;
0248     layers[0].is_virt_csrow = true;
0249     layers[1].type = EDAC_MC_LAYER_CHANNEL;
0250     layers[1].size = 1;
0251     layers[1].is_virt_csrow = false;
0252     mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
0253 
0254     if (mci == NULL)
0255         return -ENOMEM;
0256 
0257     edac_dbg(0, "mci = %p\n", mci);
0258     mci->pdev = &pdev->dev;
0259     mci->mtype_cap = MEM_FLAG_RDDR;
0260     mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
0261     mci->edac_cap = ems_mode ?
0262         (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
0263     mci->mod_name = EDAC_MOD_STR;
0264     mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
0265     mci->dev_name = pci_name(pdev);
0266     mci->edac_check = amd76x_check;
0267     mci->ctl_page_to_phys = NULL;
0268 
0269     amd76x_init_csrows(mci, pdev, ems_modes[ems_mode]);
0270     amd76x_get_error_info(mci, &discard);   /* clear counters */
0271 
0272     /* Here we assume that we will never see multiple instances of this
0273      * type of memory controller.  The ID is therefore hardcoded to 0.
0274      */
0275     if (edac_mc_add_mc(mci)) {
0276         edac_dbg(3, "failed edac_mc_add_mc()\n");
0277         goto fail;
0278     }
0279 
0280     /* allocating generic PCI control info */
0281     amd76x_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
0282     if (!amd76x_pci) {
0283         printk(KERN_WARNING
0284             "%s(): Unable to create PCI control\n",
0285             __func__);
0286         printk(KERN_WARNING
0287             "%s(): PCI error report via EDAC not setup\n",
0288             __func__);
0289     }
0290 
0291     /* get this far and it's successful */
0292     edac_dbg(3, "success\n");
0293     return 0;
0294 
0295 fail:
0296     edac_mc_free(mci);
0297     return -ENODEV;
0298 }
0299 
0300 /* returns count (>= 0), or negative on error */
0301 static int amd76x_init_one(struct pci_dev *pdev,
0302                const struct pci_device_id *ent)
0303 {
0304     edac_dbg(0, "\n");
0305 
0306     /* don't need to call pci_enable_device() */
0307     return amd76x_probe1(pdev, ent->driver_data);
0308 }
0309 
0310 /**
0311  *  amd76x_remove_one   -   driver shutdown
0312  *  @pdev: PCI device being handed back
0313  *
0314  *  Called when the driver is unloaded. Find the matching mci
0315  *  structure for the device then delete the mci and free the
0316  *  resources.
0317  */
0318 static void amd76x_remove_one(struct pci_dev *pdev)
0319 {
0320     struct mem_ctl_info *mci;
0321 
0322     edac_dbg(0, "\n");
0323 
0324     if (amd76x_pci)
0325         edac_pci_release_generic_ctl(amd76x_pci);
0326 
0327     if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
0328         return;
0329 
0330     edac_mc_free(mci);
0331 }
0332 
0333 static const struct pci_device_id amd76x_pci_tbl[] = {
0334     {
0335      PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
0336      AMD762},
0337     {
0338      PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
0339      AMD761},
0340     {
0341      0,
0342      }          /* 0 terminated list. */
0343 };
0344 
0345 MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
0346 
0347 static struct pci_driver amd76x_driver = {
0348     .name = EDAC_MOD_STR,
0349     .probe = amd76x_init_one,
0350     .remove = amd76x_remove_one,
0351     .id_table = amd76x_pci_tbl,
0352 };
0353 
0354 static int __init amd76x_init(void)
0355 {
0356        /* Ensure that the OPSTATE is set correctly for POLL or NMI */
0357        opstate_init();
0358 
0359     return pci_register_driver(&amd76x_driver);
0360 }
0361 
0362 static void __exit amd76x_exit(void)
0363 {
0364     pci_unregister_driver(&amd76x_driver);
0365 }
0366 
0367 module_init(amd76x_init);
0368 module_exit(amd76x_exit);
0369 
0370 MODULE_LICENSE("GPL");
0371 MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
0372 MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
0373 
0374 module_param(edac_op_state, int, 0444);
0375 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");