root/drivers/edac/aspeed_edac.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. regmap_reg_write
  2. regmap_reg_read
  3. regmap_is_volatile
  4. count_rec
  5. count_un_rec
  6. mcr_isr
  7. config_irq
  8. init_csrows
  9. aspeed_probe
  10. aspeed_remove
  11. aspeed_init
  12. aspeed_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright 2018, 2019 Cisco Systems
   4  */
   5 
   6 #include <linux/edac.h>
   7 #include <linux/module.h>
   8 #include <linux/init.h>
   9 #include <linux/interrupt.h>
  10 #include <linux/platform_device.h>
  11 #include <linux/stop_machine.h>
  12 #include <linux/io.h>
  13 #include <linux/of_address.h>
  14 #include <linux/regmap.h>
  15 #include "edac_module.h"
  16 
  17 
  18 #define DRV_NAME "aspeed-edac"
  19 
  20 
  21 #define ASPEED_MCR_PROT        0x00 /* protection key register */
  22 #define ASPEED_MCR_CONF        0x04 /* configuration register */
  23 #define ASPEED_MCR_INTR_CTRL   0x50 /* interrupt control/status register */
  24 #define ASPEED_MCR_ADDR_UNREC  0x58 /* address of first un-recoverable error */
  25 #define ASPEED_MCR_ADDR_REC    0x5c /* address of last recoverable error */
  26 #define ASPEED_MCR_LAST        ASPEED_MCR_ADDR_REC
  27 
  28 
  29 #define ASPEED_MCR_PROT_PASSWD              0xfc600309
  30 #define ASPEED_MCR_CONF_DRAM_TYPE               BIT(4)
  31 #define ASPEED_MCR_CONF_ECC                     BIT(7)
  32 #define ASPEED_MCR_INTR_CTRL_CLEAR             BIT(31)
  33 #define ASPEED_MCR_INTR_CTRL_CNT_REC   GENMASK(23, 16)
  34 #define ASPEED_MCR_INTR_CTRL_CNT_UNREC GENMASK(15, 12)
  35 #define ASPEED_MCR_INTR_CTRL_ENABLE  (BIT(0) | BIT(1))
  36 
  37 
  38 static struct regmap *aspeed_regmap;
  39 
  40 
  41 static int regmap_reg_write(void *context, unsigned int reg, unsigned int val)
  42 {
  43         void __iomem *regs = (void __iomem *)context;
  44 
  45         /* enable write to MCR register set */
  46         writel(ASPEED_MCR_PROT_PASSWD, regs + ASPEED_MCR_PROT);
  47 
  48         writel(val, regs + reg);
  49 
  50         /* disable write to MCR register set */
  51         writel(~ASPEED_MCR_PROT_PASSWD, regs + ASPEED_MCR_PROT);
  52 
  53         return 0;
  54 }
  55 
  56 
  57 static int regmap_reg_read(void *context, unsigned int reg, unsigned int *val)
  58 {
  59         void __iomem *regs = (void __iomem *)context;
  60 
  61         *val = readl(regs + reg);
  62 
  63         return 0;
  64 }
  65 
  66 static bool regmap_is_volatile(struct device *dev, unsigned int reg)
  67 {
  68         switch (reg) {
  69         case ASPEED_MCR_PROT:
  70         case ASPEED_MCR_INTR_CTRL:
  71         case ASPEED_MCR_ADDR_UNREC:
  72         case ASPEED_MCR_ADDR_REC:
  73                 return true;
  74         default:
  75                 return false;
  76         }
  77 }
  78 
  79 
  80 static const struct regmap_config aspeed_regmap_config = {
  81         .reg_bits = 32,
  82         .val_bits = 32,
  83         .reg_stride = 4,
  84         .max_register = ASPEED_MCR_LAST,
  85         .reg_write = regmap_reg_write,
  86         .reg_read = regmap_reg_read,
  87         .volatile_reg = regmap_is_volatile,
  88         .fast_io = true,
  89 };
  90 
  91 
  92 static void count_rec(struct mem_ctl_info *mci, u8 rec_cnt, u32 rec_addr)
  93 {
  94         struct csrow_info *csrow = mci->csrows[0];
  95         u32 page, offset, syndrome;
  96 
  97         if (!rec_cnt)
  98                 return;
  99 
 100         /* report first few errors (if there are) */
 101         /* note: no addresses are recorded */
 102         if (rec_cnt > 1) {
 103                 /* page, offset and syndrome are not available */
 104                 page = 0;
 105                 offset = 0;
 106                 syndrome = 0;
 107                 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, rec_cnt-1,
 108                                      page, offset, syndrome, 0, 0, -1,
 109                                      "address(es) not available", "");
 110         }
 111 
 112         /* report last error */
 113         /* note: rec_addr is the last recoverable error addr */
 114         page = rec_addr >> PAGE_SHIFT;
 115         offset = rec_addr & ~PAGE_MASK;
 116         /* syndrome is not available */
 117         syndrome = 0;
 118         edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
 119                              csrow->first_page + page, offset, syndrome,
 120                              0, 0, -1, "", "");
 121 }
 122 
 123 
 124 static void count_un_rec(struct mem_ctl_info *mci, u8 un_rec_cnt,
 125                          u32 un_rec_addr)
 126 {
 127         struct csrow_info *csrow = mci->csrows[0];
 128         u32 page, offset, syndrome;
 129 
 130         if (!un_rec_cnt)
 131                 return;
 132 
 133         /* report 1. error */
 134         /* note: un_rec_addr is the first unrecoverable error addr */
 135         page = un_rec_addr >> PAGE_SHIFT;
 136         offset = un_rec_addr & ~PAGE_MASK;
 137         /* syndrome is not available */
 138         syndrome = 0;
 139         edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
 140                              csrow->first_page + page, offset, syndrome,
 141                              0, 0, -1, "", "");
 142 
 143         /* report further errors (if there are) */
 144         /* note: no addresses are recorded */
 145         if (un_rec_cnt > 1) {
 146                 /* page, offset and syndrome are not available */
 147                 page = 0;
 148                 offset = 0;
 149                 syndrome = 0;
 150                 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, un_rec_cnt-1,
 151                                      page, offset, syndrome, 0, 0, -1,
 152                                      "address(es) not available", "");
 153         }
 154 }
 155 
 156 
 157 static irqreturn_t mcr_isr(int irq, void *arg)
 158 {
 159         struct mem_ctl_info *mci = arg;
 160         u32 rec_addr, un_rec_addr;
 161         u32 reg50, reg5c, reg58;
 162         u8  rec_cnt, un_rec_cnt;
 163 
 164         regmap_read(aspeed_regmap, ASPEED_MCR_INTR_CTRL, &reg50);
 165         dev_dbg(mci->pdev, "received edac interrupt w/ mcr register 50: 0x%x\n",
 166                 reg50);
 167 
 168         /* collect data about recoverable and unrecoverable errors */
 169         rec_cnt = (reg50 & ASPEED_MCR_INTR_CTRL_CNT_REC) >> 16;
 170         un_rec_cnt = (reg50 & ASPEED_MCR_INTR_CTRL_CNT_UNREC) >> 12;
 171 
 172         dev_dbg(mci->pdev, "%d recoverable interrupts and %d unrecoverable interrupts\n",
 173                 rec_cnt, un_rec_cnt);
 174 
 175         regmap_read(aspeed_regmap, ASPEED_MCR_ADDR_UNREC, &reg58);
 176         un_rec_addr = reg58;
 177 
 178         regmap_read(aspeed_regmap, ASPEED_MCR_ADDR_REC, &reg5c);
 179         rec_addr = reg5c;
 180 
 181         /* clear interrupt flags and error counters: */
 182         regmap_update_bits(aspeed_regmap, ASPEED_MCR_INTR_CTRL,
 183                            ASPEED_MCR_INTR_CTRL_CLEAR,
 184                            ASPEED_MCR_INTR_CTRL_CLEAR);
 185 
 186         regmap_update_bits(aspeed_regmap, ASPEED_MCR_INTR_CTRL,
 187                            ASPEED_MCR_INTR_CTRL_CLEAR, 0);
 188 
 189         /* process recoverable and unrecoverable errors */
 190         count_rec(mci, rec_cnt, rec_addr);
 191         count_un_rec(mci, un_rec_cnt, un_rec_addr);
 192 
 193         if (!rec_cnt && !un_rec_cnt)
 194                 dev_dbg(mci->pdev, "received edac interrupt, but did not find any ECC counters\n");
 195 
 196         regmap_read(aspeed_regmap, ASPEED_MCR_INTR_CTRL, &reg50);
 197         dev_dbg(mci->pdev, "edac interrupt handled. mcr reg 50 is now: 0x%x\n",
 198                 reg50);
 199 
 200         return IRQ_HANDLED;
 201 }
 202 
 203 
 204 static int config_irq(void *ctx, struct platform_device *pdev)
 205 {
 206         int irq;
 207         int rc;
 208 
 209         /* register interrupt handler */
 210         irq = platform_get_irq(pdev, 0);
 211         dev_dbg(&pdev->dev, "got irq %d\n", irq);
 212         if (!irq)
 213                 return -ENODEV;
 214 
 215         rc = devm_request_irq(&pdev->dev, irq, mcr_isr, IRQF_TRIGGER_HIGH,
 216                               DRV_NAME, ctx);
 217         if (rc) {
 218                 dev_err(&pdev->dev, "unable to request irq %d\n", irq);
 219                 return rc;
 220         }
 221 
 222         /* enable interrupts */
 223         regmap_update_bits(aspeed_regmap, ASPEED_MCR_INTR_CTRL,
 224                            ASPEED_MCR_INTR_CTRL_ENABLE,
 225                            ASPEED_MCR_INTR_CTRL_ENABLE);
 226 
 227         return 0;
 228 }
 229 
 230 
 231 static int init_csrows(struct mem_ctl_info *mci)
 232 {
 233         struct csrow_info *csrow = mci->csrows[0];
 234         u32 nr_pages, dram_type;
 235         struct dimm_info *dimm;
 236         struct device_node *np;
 237         struct resource r;
 238         u32 reg04;
 239         int rc;
 240 
 241         /* retrieve info about physical memory from device tree */
 242         np = of_find_node_by_path("/memory");
 243         if (!np) {
 244                 dev_err(mci->pdev, "dt: missing /memory node\n");
 245                 return -ENODEV;
 246         };
 247 
 248         rc = of_address_to_resource(np, 0, &r);
 249 
 250         of_node_put(np);
 251 
 252         if (rc) {
 253                 dev_err(mci->pdev, "dt: failed requesting resource for /memory node\n");
 254                 return rc;
 255         };
 256 
 257         dev_dbg(mci->pdev, "dt: /memory node resources: first page r.start=0x%x, resource_size=0x%x, PAGE_SHIFT macro=0x%x\n",
 258                 r.start, resource_size(&r), PAGE_SHIFT);
 259 
 260         csrow->first_page = r.start >> PAGE_SHIFT;
 261         nr_pages = resource_size(&r) >> PAGE_SHIFT;
 262         csrow->last_page = csrow->first_page + nr_pages - 1;
 263 
 264         regmap_read(aspeed_regmap, ASPEED_MCR_CONF, &reg04);
 265         dram_type = (reg04 & ASPEED_MCR_CONF_DRAM_TYPE) ? MEM_DDR4 : MEM_DDR3;
 266 
 267         dimm = csrow->channels[0]->dimm;
 268         dimm->mtype = dram_type;
 269         dimm->edac_mode = EDAC_SECDED;
 270         dimm->nr_pages = nr_pages / csrow->nr_channels;
 271 
 272         dev_dbg(mci->pdev, "initialized dimm with first_page=0x%lx and nr_pages=0x%x\n",
 273                 csrow->first_page, nr_pages);
 274 
 275         return 0;
 276 }
 277 
 278 
 279 static int aspeed_probe(struct platform_device *pdev)
 280 {
 281         struct device *dev = &pdev->dev;
 282         struct edac_mc_layer layers[2];
 283         struct mem_ctl_info *mci;
 284         struct resource *res;
 285         void __iomem *regs;
 286         u32 reg04;
 287         int rc;
 288 
 289         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 290         if (!res)
 291                 return -ENOENT;
 292 
 293         regs = devm_ioremap_resource(dev, res);
 294         if (IS_ERR(regs))
 295                 return PTR_ERR(regs);
 296 
 297         aspeed_regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
 298                                          &aspeed_regmap_config);
 299         if (IS_ERR(aspeed_regmap))
 300                 return PTR_ERR(aspeed_regmap);
 301 
 302         /* bail out if ECC mode is not configured */
 303         regmap_read(aspeed_regmap, ASPEED_MCR_CONF, &reg04);
 304         if (!(reg04 & ASPEED_MCR_CONF_ECC)) {
 305                 dev_err(&pdev->dev, "ECC mode is not configured in u-boot\n");
 306                 return -EPERM;
 307         }
 308 
 309         edac_op_state = EDAC_OPSTATE_INT;
 310 
 311         /* allocate & init EDAC MC data structure */
 312         layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
 313         layers[0].size = 1;
 314         layers[0].is_virt_csrow = true;
 315         layers[1].type = EDAC_MC_LAYER_CHANNEL;
 316         layers[1].size = 1;
 317         layers[1].is_virt_csrow = false;
 318 
 319         mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
 320         if (!mci)
 321                 return -ENOMEM;
 322 
 323         mci->pdev = &pdev->dev;
 324         mci->mtype_cap = MEM_FLAG_DDR3 | MEM_FLAG_DDR4;
 325         mci->edac_ctl_cap = EDAC_FLAG_SECDED;
 326         mci->edac_cap = EDAC_FLAG_SECDED;
 327         mci->scrub_cap = SCRUB_FLAG_HW_SRC;
 328         mci->scrub_mode = SCRUB_HW_SRC;
 329         mci->mod_name = DRV_NAME;
 330         mci->ctl_name = "MIC";
 331         mci->dev_name = dev_name(&pdev->dev);
 332 
 333         rc = init_csrows(mci);
 334         if (rc) {
 335                 dev_err(&pdev->dev, "failed to init csrows\n");
 336                 goto probe_exit02;
 337         }
 338 
 339         platform_set_drvdata(pdev, mci);
 340 
 341         /* register with edac core */
 342         rc = edac_mc_add_mc(mci);
 343         if (rc) {
 344                 dev_err(&pdev->dev, "failed to register with EDAC core\n");
 345                 goto probe_exit02;
 346         }
 347 
 348         /* register interrupt handler and enable interrupts */
 349         rc = config_irq(mci, pdev);
 350         if (rc) {
 351                 dev_err(&pdev->dev, "failed setting up irq\n");
 352                 goto probe_exit01;
 353         }
 354 
 355         return 0;
 356 
 357 probe_exit01:
 358         edac_mc_del_mc(&pdev->dev);
 359 probe_exit02:
 360         edac_mc_free(mci);
 361         return rc;
 362 }
 363 
 364 
 365 static int aspeed_remove(struct platform_device *pdev)
 366 {
 367         struct mem_ctl_info *mci;
 368 
 369         /* disable interrupts */
 370         regmap_update_bits(aspeed_regmap, ASPEED_MCR_INTR_CTRL,
 371                            ASPEED_MCR_INTR_CTRL_ENABLE, 0);
 372 
 373         /* free resources */
 374         mci = edac_mc_del_mc(&pdev->dev);
 375         if (mci)
 376                 edac_mc_free(mci);
 377 
 378         return 0;
 379 }
 380 
 381 
 382 static const struct of_device_id aspeed_of_match[] = {
 383         { .compatible = "aspeed,ast2500-sdram-edac" },
 384         {},
 385 };
 386 
 387 
 388 static struct platform_driver aspeed_driver = {
 389         .driver         = {
 390                 .name   = DRV_NAME,
 391                 .of_match_table = aspeed_of_match
 392         },
 393         .probe          = aspeed_probe,
 394         .remove         = aspeed_remove
 395 };
 396 
 397 
 398 static int __init aspeed_init(void)
 399 {
 400         return platform_driver_register(&aspeed_driver);
 401 }
 402 
 403 
 404 static void __exit aspeed_exit(void)
 405 {
 406         platform_driver_unregister(&aspeed_driver);
 407 }
 408 
 409 
 410 module_init(aspeed_init);
 411 module_exit(aspeed_exit);
 412 
 413 
 414 MODULE_LICENSE("GPL");
 415 MODULE_AUTHOR("Stefan Schaeckeler <sschaeck@cisco.com>");
 416 MODULE_DESCRIPTION("Aspeed AST2500 EDAC driver");
 417 MODULE_VERSION("1.0");

/* [<][>][^][v][top][bottom][index][help] */