Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2017 Pengutronix, Jan Luebbe <kernel@pengutronix.de>
0004  */
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/edac.h>
0008 #include <linux/of_platform.h>
0009 
0010 #include <asm/hardware/cache-l2x0.h>
0011 #include <asm/hardware/cache-aurora-l2.h>
0012 
0013 #include "edac_mc.h"
0014 #include "edac_device.h"
0015 #include "edac_module.h"
0016 
0017 /************************ EDAC MC (DDR RAM) ********************************/
0018 
0019 #define SDRAM_NUM_CS 4
0020 
0021 #define SDRAM_CONFIG_REG        0x0
0022 #define SDRAM_CONFIG_ECC_MASK         BIT(18)
0023 #define SDRAM_CONFIG_REGISTERED_MASK  BIT(17)
0024 #define SDRAM_CONFIG_BUS_WIDTH_MASK   BIT(15)
0025 
0026 #define SDRAM_ADDR_CTRL_REG     0x10
0027 #define SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs) (20+cs)
0028 #define SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(cs)   (0x1 << SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs))
0029 #define SDRAM_ADDR_CTRL_ADDR_SEL_MASK(cs)    BIT(16+cs)
0030 #define SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs)  (cs*4+2)
0031 #define SDRAM_ADDR_CTRL_SIZE_LOW_MASK(cs)    (0x3 << SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs))
0032 #define SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs)    (cs*4)
0033 #define SDRAM_ADDR_CTRL_STRUCT_MASK(cs)      (0x3 << SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs))
0034 
0035 #define SDRAM_ERR_DATA_H_REG    0x40
0036 #define SDRAM_ERR_DATA_L_REG    0x44
0037 
0038 #define SDRAM_ERR_RECV_ECC_REG  0x48
0039 #define SDRAM_ERR_RECV_ECC_VALUE_MASK 0xff
0040 
0041 #define SDRAM_ERR_CALC_ECC_REG  0x4c
0042 #define SDRAM_ERR_CALC_ECC_ROW_OFFSET 8
0043 #define SDRAM_ERR_CALC_ECC_ROW_MASK   (0xffff << SDRAM_ERR_CALC_ECC_ROW_OFFSET)
0044 #define SDRAM_ERR_CALC_ECC_VALUE_MASK 0xff
0045 
0046 #define SDRAM_ERR_ADDR_REG      0x50
0047 #define SDRAM_ERR_ADDR_BANK_OFFSET    23
0048 #define SDRAM_ERR_ADDR_BANK_MASK      (0x7 << SDRAM_ERR_ADDR_BANK_OFFSET)
0049 #define SDRAM_ERR_ADDR_COL_OFFSET     8
0050 #define SDRAM_ERR_ADDR_COL_MASK       (0x7fff << SDRAM_ERR_ADDR_COL_OFFSET)
0051 #define SDRAM_ERR_ADDR_CS_OFFSET      1
0052 #define SDRAM_ERR_ADDR_CS_MASK        (0x3 << SDRAM_ERR_ADDR_CS_OFFSET)
0053 #define SDRAM_ERR_ADDR_TYPE_MASK      BIT(0)
0054 
0055 #define SDRAM_ERR_CTRL_REG      0x54
0056 #define SDRAM_ERR_CTRL_THR_OFFSET     16
0057 #define SDRAM_ERR_CTRL_THR_MASK       (0xff << SDRAM_ERR_CTRL_THR_OFFSET)
0058 #define SDRAM_ERR_CTRL_PROP_MASK      BIT(9)
0059 
0060 #define SDRAM_ERR_SBE_COUNT_REG 0x58
0061 #define SDRAM_ERR_DBE_COUNT_REG 0x5c
0062 
0063 #define SDRAM_ERR_CAUSE_ERR_REG 0xd0
0064 #define SDRAM_ERR_CAUSE_MSG_REG 0xd8
0065 #define SDRAM_ERR_CAUSE_DBE_MASK      BIT(1)
0066 #define SDRAM_ERR_CAUSE_SBE_MASK      BIT(0)
0067 
0068 #define SDRAM_RANK_CTRL_REG 0x1e0
0069 #define SDRAM_RANK_CTRL_EXIST_MASK(cs) BIT(cs)
0070 
0071 struct axp_mc_drvdata {
0072     void __iomem *base;
0073     /* width in bytes */
0074     unsigned int width;
0075     /* bank interleaving */
0076     bool cs_addr_sel[SDRAM_NUM_CS];
0077 
0078     char msg[128];
0079 };
0080 
0081 /* derived from "DRAM Address Multiplexing" in the ARMADA XP Functional Spec */
0082 static uint32_t axp_mc_calc_address(struct axp_mc_drvdata *drvdata,
0083                     uint8_t cs, uint8_t bank, uint16_t row,
0084                     uint16_t col)
0085 {
0086     if (drvdata->width == 8) {
0087         /* 64 bit */
0088         if (drvdata->cs_addr_sel[cs])
0089             /* bank interleaved */
0090             return (((row & 0xfff8) << 16) |
0091                 ((bank & 0x7) << 16) |
0092                 ((row & 0x7) << 13) |
0093                 ((col & 0x3ff) << 3));
0094         else
0095             return (((row & 0xffff << 16) |
0096                  ((bank & 0x7) << 13) |
0097                  ((col & 0x3ff)) << 3));
0098     } else if (drvdata->width == 4) {
0099         /* 32 bit */
0100         if (drvdata->cs_addr_sel[cs])
0101             /* bank interleaved */
0102             return (((row & 0xfff0) << 15) |
0103                 ((bank & 0x7) << 16) |
0104                 ((row & 0xf) << 12) |
0105                 ((col & 0x3ff) << 2));
0106         else
0107             return (((row & 0xffff << 15) |
0108                  ((bank & 0x7) << 12) |
0109                  ((col & 0x3ff)) << 2));
0110     } else {
0111         /* 16 bit */
0112         if (drvdata->cs_addr_sel[cs])
0113             /* bank interleaved */
0114             return (((row & 0xffe0) << 14) |
0115                 ((bank & 0x7) << 16) |
0116                 ((row & 0x1f) << 11) |
0117                 ((col & 0x3ff) << 1));
0118         else
0119             return (((row & 0xffff << 14) |
0120                  ((bank & 0x7) << 11) |
0121                  ((col & 0x3ff)) << 1));
0122     }
0123 }
0124 
0125 static void axp_mc_check(struct mem_ctl_info *mci)
0126 {
0127     struct axp_mc_drvdata *drvdata = mci->pvt_info;
0128     uint32_t data_h, data_l, recv_ecc, calc_ecc, addr;
0129     uint32_t cnt_sbe, cnt_dbe, cause_err, cause_msg;
0130     uint32_t row_val, col_val, bank_val, addr_val;
0131     uint8_t syndrome_val, cs_val;
0132     char *msg = drvdata->msg;
0133 
0134     data_h    = readl(drvdata->base + SDRAM_ERR_DATA_H_REG);
0135     data_l    = readl(drvdata->base + SDRAM_ERR_DATA_L_REG);
0136     recv_ecc  = readl(drvdata->base + SDRAM_ERR_RECV_ECC_REG);
0137     calc_ecc  = readl(drvdata->base + SDRAM_ERR_CALC_ECC_REG);
0138     addr      = readl(drvdata->base + SDRAM_ERR_ADDR_REG);
0139     cnt_sbe   = readl(drvdata->base + SDRAM_ERR_SBE_COUNT_REG);
0140     cnt_dbe   = readl(drvdata->base + SDRAM_ERR_DBE_COUNT_REG);
0141     cause_err = readl(drvdata->base + SDRAM_ERR_CAUSE_ERR_REG);
0142     cause_msg = readl(drvdata->base + SDRAM_ERR_CAUSE_MSG_REG);
0143 
0144     /* clear cause registers */
0145     writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK),
0146            drvdata->base + SDRAM_ERR_CAUSE_ERR_REG);
0147     writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK),
0148            drvdata->base + SDRAM_ERR_CAUSE_MSG_REG);
0149 
0150     /* clear error counter registers */
0151     if (cnt_sbe)
0152         writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG);
0153     if (cnt_dbe)
0154         writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG);
0155 
0156     if (!cnt_sbe && !cnt_dbe)
0157         return;
0158 
0159     if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) {
0160         if (cnt_sbe)
0161             cnt_sbe--;
0162         else
0163             dev_warn(mci->pdev, "inconsistent SBE count detected\n");
0164     } else {
0165         if (cnt_dbe)
0166             cnt_dbe--;
0167         else
0168             dev_warn(mci->pdev, "inconsistent DBE count detected\n");
0169     }
0170 
0171     /* report earlier errors */
0172     if (cnt_sbe)
0173         edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
0174                      cnt_sbe, /* error count */
0175                      0, 0, 0, /* pfn, offset, syndrome */
0176                      -1, -1, -1, /* top, mid, low layer */
0177                      mci->ctl_name,
0178                      "details unavailable (multiple errors)");
0179     if (cnt_dbe)
0180         edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
0181                      cnt_dbe, /* error count */
0182                      0, 0, 0, /* pfn, offset, syndrome */
0183                      -1, -1, -1, /* top, mid, low layer */
0184                      mci->ctl_name,
0185                      "details unavailable (multiple errors)");
0186 
0187     /* report details for most recent error */
0188     cs_val   = (addr & SDRAM_ERR_ADDR_CS_MASK) >> SDRAM_ERR_ADDR_CS_OFFSET;
0189     bank_val = (addr & SDRAM_ERR_ADDR_BANK_MASK) >> SDRAM_ERR_ADDR_BANK_OFFSET;
0190     row_val  = (calc_ecc & SDRAM_ERR_CALC_ECC_ROW_MASK) >> SDRAM_ERR_CALC_ECC_ROW_OFFSET;
0191     col_val  = (addr & SDRAM_ERR_ADDR_COL_MASK) >> SDRAM_ERR_ADDR_COL_OFFSET;
0192     syndrome_val = (recv_ecc ^ calc_ecc) & 0xff;
0193     addr_val = axp_mc_calc_address(drvdata, cs_val, bank_val, row_val,
0194                        col_val);
0195     msg += sprintf(msg, "row=0x%04x ", row_val); /* 11 chars */
0196     msg += sprintf(msg, "bank=0x%x ", bank_val); /*  9 chars */
0197     msg += sprintf(msg, "col=0x%04x ", col_val); /* 11 chars */
0198     msg += sprintf(msg, "cs=%d", cs_val);        /*  4 chars */
0199 
0200     if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) {
0201         edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
0202                      1, /* error count */
0203                      addr_val >> PAGE_SHIFT,
0204                      addr_val & ~PAGE_MASK,
0205                      syndrome_val,
0206                      cs_val, -1, -1, /* top, mid, low layer */
0207                      mci->ctl_name, drvdata->msg);
0208     } else {
0209         edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
0210                      1, /* error count */
0211                      addr_val >> PAGE_SHIFT,
0212                      addr_val & ~PAGE_MASK,
0213                      syndrome_val,
0214                      cs_val, -1, -1, /* top, mid, low layer */
0215                      mci->ctl_name, drvdata->msg);
0216     }
0217 }
0218 
0219 static void axp_mc_read_config(struct mem_ctl_info *mci)
0220 {
0221     struct axp_mc_drvdata *drvdata = mci->pvt_info;
0222     uint32_t config, addr_ctrl, rank_ctrl;
0223     unsigned int i, cs_struct, cs_size;
0224     struct dimm_info *dimm;
0225 
0226     config = readl(drvdata->base + SDRAM_CONFIG_REG);
0227     if (config & SDRAM_CONFIG_BUS_WIDTH_MASK)
0228         /* 64 bit */
0229         drvdata->width = 8;
0230     else
0231         /* 32 bit */
0232         drvdata->width = 4;
0233 
0234     addr_ctrl = readl(drvdata->base + SDRAM_ADDR_CTRL_REG);
0235     rank_ctrl = readl(drvdata->base + SDRAM_RANK_CTRL_REG);
0236     for (i = 0; i < SDRAM_NUM_CS; i++) {
0237         dimm = mci->dimms[i];
0238 
0239         if (!(rank_ctrl & SDRAM_RANK_CTRL_EXIST_MASK(i)))
0240             continue;
0241 
0242         drvdata->cs_addr_sel[i] =
0243             !!(addr_ctrl & SDRAM_ADDR_CTRL_ADDR_SEL_MASK(i));
0244 
0245         cs_struct = (addr_ctrl & SDRAM_ADDR_CTRL_STRUCT_MASK(i)) >> SDRAM_ADDR_CTRL_STRUCT_OFFSET(i);
0246         cs_size   = ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(i)) >> (SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(i) - 2) |
0247                 ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_LOW_MASK(i)) >> SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(i)));
0248 
0249         switch (cs_size) {
0250         case 0: /* 2GBit */
0251             dimm->nr_pages = 524288;
0252             break;
0253         case 1: /* 256MBit */
0254             dimm->nr_pages = 65536;
0255             break;
0256         case 2: /* 512MBit */
0257             dimm->nr_pages = 131072;
0258             break;
0259         case 3: /* 1GBit */
0260             dimm->nr_pages = 262144;
0261             break;
0262         case 4: /* 4GBit */
0263             dimm->nr_pages = 1048576;
0264             break;
0265         case 5: /* 8GBit */
0266             dimm->nr_pages = 2097152;
0267             break;
0268         }
0269         dimm->grain = 8;
0270         dimm->dtype = cs_struct ? DEV_X16 : DEV_X8;
0271         dimm->mtype = (config & SDRAM_CONFIG_REGISTERED_MASK) ?
0272             MEM_RDDR3 : MEM_DDR3;
0273         dimm->edac_mode = EDAC_SECDED;
0274     }
0275 }
0276 
0277 static const struct of_device_id axp_mc_of_match[] = {
0278     {.compatible = "marvell,armada-xp-sdram-controller",},
0279     {},
0280 };
0281 MODULE_DEVICE_TABLE(of, axp_mc_of_match);
0282 
0283 static int axp_mc_probe(struct platform_device *pdev)
0284 {
0285     struct axp_mc_drvdata *drvdata;
0286     struct edac_mc_layer layers[1];
0287     const struct of_device_id *id;
0288     struct mem_ctl_info *mci;
0289     void __iomem *base;
0290     uint32_t config;
0291 
0292     base = devm_platform_ioremap_resource(pdev, 0);
0293     if (IS_ERR(base)) {
0294         dev_err(&pdev->dev, "Unable to map regs\n");
0295         return PTR_ERR(base);
0296     }
0297 
0298     config = readl(base + SDRAM_CONFIG_REG);
0299     if (!(config & SDRAM_CONFIG_ECC_MASK)) {
0300         dev_warn(&pdev->dev, "SDRAM ECC is not enabled\n");
0301         return -EINVAL;
0302     }
0303 
0304     layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
0305     layers[0].size = SDRAM_NUM_CS;
0306     layers[0].is_virt_csrow = true;
0307 
0308     mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*drvdata));
0309     if (!mci)
0310         return -ENOMEM;
0311 
0312     drvdata = mci->pvt_info;
0313     drvdata->base = base;
0314     mci->pdev = &pdev->dev;
0315     platform_set_drvdata(pdev, mci);
0316 
0317     id = of_match_device(axp_mc_of_match, &pdev->dev);
0318     mci->edac_check = axp_mc_check;
0319     mci->mtype_cap = MEM_FLAG_DDR3;
0320     mci->edac_cap = EDAC_FLAG_SECDED;
0321     mci->mod_name = pdev->dev.driver->name;
0322     mci->ctl_name = id ? id->compatible : "unknown";
0323     mci->dev_name = dev_name(&pdev->dev);
0324     mci->scrub_mode = SCRUB_NONE;
0325 
0326     axp_mc_read_config(mci);
0327 
0328     /* These SoCs have a reduced width bus */
0329     if (of_machine_is_compatible("marvell,armada380") ||
0330         of_machine_is_compatible("marvell,armadaxp-98dx3236"))
0331         drvdata->width /= 2;
0332 
0333     /* configure SBE threshold */
0334     /* it seems that SBEs are not captured otherwise */
0335     writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG);
0336 
0337     /* clear cause registers */
0338     writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_ERR_REG);
0339     writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_MSG_REG);
0340 
0341     /* clear counter registers */
0342     writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG);
0343     writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG);
0344 
0345     if (edac_mc_add_mc(mci)) {
0346         edac_mc_free(mci);
0347         return -EINVAL;
0348     }
0349     edac_op_state = EDAC_OPSTATE_POLL;
0350 
0351     return 0;
0352 }
0353 
0354 static int axp_mc_remove(struct platform_device *pdev)
0355 {
0356     struct mem_ctl_info *mci = platform_get_drvdata(pdev);
0357 
0358     edac_mc_del_mc(&pdev->dev);
0359     edac_mc_free(mci);
0360     platform_set_drvdata(pdev, NULL);
0361 
0362     return 0;
0363 }
0364 
0365 static struct platform_driver axp_mc_driver = {
0366     .probe = axp_mc_probe,
0367     .remove = axp_mc_remove,
0368     .driver = {
0369         .name = "armada_xp_mc_edac",
0370         .of_match_table = of_match_ptr(axp_mc_of_match),
0371     },
0372 };
0373 
0374 /************************ EDAC Device (L2 Cache) ***************************/
0375 
0376 struct aurora_l2_drvdata {
0377     void __iomem *base;
0378 
0379     char msg[128];
0380 
0381     /* error injection via debugfs */
0382     uint32_t inject_addr;
0383     uint32_t inject_mask;
0384     uint8_t inject_ctl;
0385 
0386     struct dentry *debugfs;
0387 };
0388 
0389 #ifdef CONFIG_EDAC_DEBUG
0390 static void aurora_l2_inject(struct aurora_l2_drvdata *drvdata)
0391 {
0392     drvdata->inject_addr &= AURORA_ERR_INJECT_CTL_ADDR_MASK;
0393     drvdata->inject_ctl &= AURORA_ERR_INJECT_CTL_EN_MASK;
0394     writel(0, drvdata->base + AURORA_ERR_INJECT_CTL_REG);
0395     writel(drvdata->inject_mask, drvdata->base + AURORA_ERR_INJECT_MASK_REG);
0396     writel(drvdata->inject_addr | drvdata->inject_ctl, drvdata->base + AURORA_ERR_INJECT_CTL_REG);
0397 }
0398 #endif
0399 
0400 static void aurora_l2_check(struct edac_device_ctl_info *dci)
0401 {
0402     struct aurora_l2_drvdata *drvdata = dci->pvt_info;
0403     uint32_t cnt, src, txn, err, attr_cap, addr_cap, way_cap;
0404     unsigned int cnt_ce, cnt_ue;
0405     char *msg = drvdata->msg;
0406     size_t size = sizeof(drvdata->msg);
0407     size_t len = 0;
0408 
0409     cnt = readl(drvdata->base + AURORA_ERR_CNT_REG);
0410     attr_cap = readl(drvdata->base + AURORA_ERR_ATTR_CAP_REG);
0411     addr_cap = readl(drvdata->base + AURORA_ERR_ADDR_CAP_REG);
0412     way_cap = readl(drvdata->base + AURORA_ERR_WAY_CAP_REG);
0413 
0414     cnt_ce = (cnt & AURORA_ERR_CNT_CE_MASK) >> AURORA_ERR_CNT_CE_OFFSET;
0415     cnt_ue = (cnt & AURORA_ERR_CNT_UE_MASK) >> AURORA_ERR_CNT_UE_OFFSET;
0416     /* clear error counter registers */
0417     if (cnt_ce || cnt_ue)
0418         writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG);
0419 
0420     if (!(attr_cap & AURORA_ERR_ATTR_CAP_VALID))
0421         goto clear_remaining;
0422 
0423     src = (attr_cap & AURORA_ERR_ATTR_SRC_MSK) >> AURORA_ERR_ATTR_SRC_OFF;
0424     if (src <= 3)
0425         len += scnprintf(msg+len, size-len, "src=CPU%d ", src);
0426     else
0427         len += scnprintf(msg+len, size-len, "src=IO ");
0428 
0429     txn =  (attr_cap & AURORA_ERR_ATTR_TXN_MSK) >> AURORA_ERR_ATTR_TXN_OFF;
0430     switch (txn) {
0431     case 0:
0432         len += scnprintf(msg+len, size-len, "txn=Data-Read ");
0433         break;
0434     case 1:
0435         len += scnprintf(msg+len, size-len, "txn=Isn-Read ");
0436         break;
0437     case 2:
0438         len += scnprintf(msg+len, size-len, "txn=Clean-Flush ");
0439         break;
0440     case 3:
0441         len += scnprintf(msg+len, size-len, "txn=Eviction ");
0442         break;
0443     case 4:
0444         len += scnprintf(msg+len, size-len,
0445                 "txn=Read-Modify-Write ");
0446         break;
0447     }
0448 
0449     err = (attr_cap & AURORA_ERR_ATTR_ERR_MSK) >> AURORA_ERR_ATTR_ERR_OFF;
0450     switch (err) {
0451     case 0:
0452         len += scnprintf(msg+len, size-len, "err=CorrECC ");
0453         break;
0454     case 1:
0455         len += scnprintf(msg+len, size-len, "err=UnCorrECC ");
0456         break;
0457     case 2:
0458         len += scnprintf(msg+len, size-len, "err=TagParity ");
0459         break;
0460     }
0461 
0462     len += scnprintf(msg+len, size-len, "addr=0x%x ", addr_cap & AURORA_ERR_ADDR_CAP_ADDR_MASK);
0463     len += scnprintf(msg+len, size-len, "index=0x%x ", (way_cap & AURORA_ERR_WAY_IDX_MSK) >> AURORA_ERR_WAY_IDX_OFF);
0464     len += scnprintf(msg+len, size-len, "way=0x%x", (way_cap & AURORA_ERR_WAY_CAP_WAY_MASK) >> AURORA_ERR_WAY_CAP_WAY_OFFSET);
0465 
0466     /* clear error capture registers */
0467     writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG);
0468     if (err) {
0469         /* UnCorrECC or TagParity */
0470         if (cnt_ue)
0471             cnt_ue--;
0472         edac_device_handle_ue(dci, 0, 0, drvdata->msg);
0473     } else {
0474         if (cnt_ce)
0475             cnt_ce--;
0476         edac_device_handle_ce(dci, 0, 0, drvdata->msg);
0477     }
0478 
0479 clear_remaining:
0480     /* report remaining errors */
0481     while (cnt_ue--)
0482         edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)");
0483     while (cnt_ce--)
0484         edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)");
0485 }
0486 
0487 static void aurora_l2_poll(struct edac_device_ctl_info *dci)
0488 {
0489 #ifdef CONFIG_EDAC_DEBUG
0490     struct aurora_l2_drvdata *drvdata = dci->pvt_info;
0491 #endif
0492 
0493     aurora_l2_check(dci);
0494 #ifdef CONFIG_EDAC_DEBUG
0495     aurora_l2_inject(drvdata);
0496 #endif
0497 }
0498 
0499 static const struct of_device_id aurora_l2_of_match[] = {
0500     {.compatible = "marvell,aurora-system-cache",},
0501     {},
0502 };
0503 MODULE_DEVICE_TABLE(of, aurora_l2_of_match);
0504 
0505 static int aurora_l2_probe(struct platform_device *pdev)
0506 {
0507     struct aurora_l2_drvdata *drvdata;
0508     struct edac_device_ctl_info *dci;
0509     const struct of_device_id *id;
0510     uint32_t l2x0_aux_ctrl;
0511     void __iomem *base;
0512 
0513     base = devm_platform_ioremap_resource(pdev, 0);
0514     if (IS_ERR(base)) {
0515         dev_err(&pdev->dev, "Unable to map regs\n");
0516         return PTR_ERR(base);
0517     }
0518 
0519     l2x0_aux_ctrl = readl(base + L2X0_AUX_CTRL);
0520     if (!(l2x0_aux_ctrl & AURORA_ACR_PARITY_EN))
0521         dev_warn(&pdev->dev, "tag parity is not enabled\n");
0522     if (!(l2x0_aux_ctrl & AURORA_ACR_ECC_EN))
0523         dev_warn(&pdev->dev, "data ECC is not enabled\n");
0524 
0525     dci = edac_device_alloc_ctl_info(sizeof(*drvdata),
0526                      "cpu", 1, "L", 1, 2, NULL, 0, 0);
0527     if (!dci)
0528         return -ENOMEM;
0529 
0530     drvdata = dci->pvt_info;
0531     drvdata->base = base;
0532     dci->dev = &pdev->dev;
0533     platform_set_drvdata(pdev, dci);
0534 
0535     id = of_match_device(aurora_l2_of_match, &pdev->dev);
0536     dci->edac_check = aurora_l2_poll;
0537     dci->mod_name = pdev->dev.driver->name;
0538     dci->ctl_name = id ? id->compatible : "unknown";
0539     dci->dev_name = dev_name(&pdev->dev);
0540 
0541     /* clear registers */
0542     writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG);
0543     writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG);
0544 
0545     if (edac_device_add_device(dci)) {
0546         edac_device_free_ctl_info(dci);
0547         return -EINVAL;
0548     }
0549 
0550 #ifdef CONFIG_EDAC_DEBUG
0551     drvdata->debugfs = edac_debugfs_create_dir(dev_name(&pdev->dev));
0552     if (drvdata->debugfs) {
0553         edac_debugfs_create_x32("inject_addr", 0644,
0554                     drvdata->debugfs,
0555                     &drvdata->inject_addr);
0556         edac_debugfs_create_x32("inject_mask", 0644,
0557                     drvdata->debugfs,
0558                     &drvdata->inject_mask);
0559         edac_debugfs_create_x8("inject_ctl", 0644,
0560                        drvdata->debugfs, &drvdata->inject_ctl);
0561     }
0562 #endif
0563 
0564     return 0;
0565 }
0566 
0567 static int aurora_l2_remove(struct platform_device *pdev)
0568 {
0569     struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
0570 #ifdef CONFIG_EDAC_DEBUG
0571     struct aurora_l2_drvdata *drvdata = dci->pvt_info;
0572 
0573     edac_debugfs_remove_recursive(drvdata->debugfs);
0574 #endif
0575     edac_device_del_device(&pdev->dev);
0576     edac_device_free_ctl_info(dci);
0577     platform_set_drvdata(pdev, NULL);
0578 
0579     return 0;
0580 }
0581 
0582 static struct platform_driver aurora_l2_driver = {
0583     .probe = aurora_l2_probe,
0584     .remove = aurora_l2_remove,
0585     .driver = {
0586         .name = "aurora_l2_edac",
0587         .of_match_table = of_match_ptr(aurora_l2_of_match),
0588     },
0589 };
0590 
0591 /************************ Driver registration ******************************/
0592 
0593 static struct platform_driver * const drivers[] = {
0594     &axp_mc_driver,
0595     &aurora_l2_driver,
0596 };
0597 
0598 static int __init armada_xp_edac_init(void)
0599 {
0600     int res;
0601 
0602     /* only polling is supported */
0603     edac_op_state = EDAC_OPSTATE_POLL;
0604 
0605     res = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
0606     if (res)
0607         pr_warn("Armada XP EDAC drivers fail to register\n");
0608 
0609     return 0;
0610 }
0611 module_init(armada_xp_edac_init);
0612 
0613 static void __exit armada_xp_edac_exit(void)
0614 {
0615     platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
0616 }
0617 module_exit(armada_xp_edac_exit);
0618 
0619 MODULE_LICENSE("GPL v2");
0620 MODULE_AUTHOR("Pengutronix");
0621 MODULE_DESCRIPTION("EDAC Drivers for Marvell Armada XP SDRAM and L2 Cache Controller");