0001
0002
0003
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
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
0074 unsigned int width;
0075
0076 bool cs_addr_sel[SDRAM_NUM_CS];
0077
0078 char msg[128];
0079 };
0080
0081
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
0088 if (drvdata->cs_addr_sel[cs])
0089
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
0100 if (drvdata->cs_addr_sel[cs])
0101
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
0112 if (drvdata->cs_addr_sel[cs])
0113
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
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
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
0172 if (cnt_sbe)
0173 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
0174 cnt_sbe,
0175 0, 0, 0,
0176 -1, -1, -1,
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,
0182 0, 0, 0,
0183 -1, -1, -1,
0184 mci->ctl_name,
0185 "details unavailable (multiple errors)");
0186
0187
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);
0196 msg += sprintf(msg, "bank=0x%x ", bank_val);
0197 msg += sprintf(msg, "col=0x%04x ", col_val);
0198 msg += sprintf(msg, "cs=%d", cs_val);
0199
0200 if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) {
0201 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
0202 1,
0203 addr_val >> PAGE_SHIFT,
0204 addr_val & ~PAGE_MASK,
0205 syndrome_val,
0206 cs_val, -1, -1,
0207 mci->ctl_name, drvdata->msg);
0208 } else {
0209 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
0210 1,
0211 addr_val >> PAGE_SHIFT,
0212 addr_val & ~PAGE_MASK,
0213 syndrome_val,
0214 cs_val, -1, -1,
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
0229 drvdata->width = 8;
0230 else
0231
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:
0251 dimm->nr_pages = 524288;
0252 break;
0253 case 1:
0254 dimm->nr_pages = 65536;
0255 break;
0256 case 2:
0257 dimm->nr_pages = 131072;
0258 break;
0259 case 3:
0260 dimm->nr_pages = 262144;
0261 break;
0262 case 4:
0263 dimm->nr_pages = 1048576;
0264 break;
0265 case 5:
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
0329 if (of_machine_is_compatible("marvell,armada380") ||
0330 of_machine_is_compatible("marvell,armadaxp-98dx3236"))
0331 drvdata->width /= 2;
0332
0333
0334
0335 writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG);
0336
0337
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
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
0375
0376 struct aurora_l2_drvdata {
0377 void __iomem *base;
0378
0379 char msg[128];
0380
0381
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
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
0467 writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG);
0468 if (err) {
0469
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
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
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
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
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");