1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Freescale Memory Controller kernel module 4 * 5 * Support Power-based SoCs including MPC85xx, MPC86xx, MPC83xx and 6 * ARM-based Layerscape SoCs including LS2xxx and LS1021A. Originally 7 * split out from mpc85xx_edac EDAC driver. 8 * 9 * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc. 10 * 11 * Author: Dave Jiang <djiang@mvista.com> 12 * 13 * 2006-2007 (c) MontaVista Software, Inc. 14 */ 15 #include <linux/module.h> 16 #include <linux/init.h> 17 #include <linux/interrupt.h> 18 #include <linux/ctype.h> 19 #include <linux/io.h> 20 #include <linux/edac.h> 21 #include <linux/smp.h> 22 #include <linux/gfp.h> 23 24 #include <linux/of.h> 25 #include <linux/of_address.h> 26 #include "edac_module.h" 27 #include "fsl_ddr_edac.h" 28 29 #define EDAC_MOD_STR "fsl_ddr_edac" 30 31 static int edac_mc_idx; 32 33 static inline void __iomem *ddr_reg_addr(struct fsl_mc_pdata *pdata, unsigned int off) 34 { 35 if (pdata->flag == TYPE_IMX9 && off >= FSL_MC_DATA_ERR_INJECT_HI && off <= FSL_MC_ERR_SBE) 36 return pdata->inject_vbase + off - FSL_MC_DATA_ERR_INJECT_HI 37 + IMX9_MC_DATA_ERR_INJECT_OFF; 38 39 if (pdata->flag == TYPE_IMX9 && off >= IMX9_MC_ERR_EN) 40 return pdata->inject_vbase + off - IMX9_MC_ERR_EN; 41 42 return pdata->mc_vbase + off; 43 } 44 45 static inline u32 ddr_in32(struct fsl_mc_pdata *pdata, unsigned int off) 46 { 47 void __iomem *addr = ddr_reg_addr(pdata, off); 48 49 return pdata->little_endian ? ioread32(addr) : ioread32be(addr); 50 } 51 52 static inline void ddr_out32(struct fsl_mc_pdata *pdata, unsigned int off, u32 value) 53 { 54 void __iomem *addr = ddr_reg_addr(pdata, off); 55 56 if (pdata->little_endian) 57 iowrite32(value, addr); 58 else 59 iowrite32be(value, addr); 60 } 61 62 #ifdef CONFIG_EDAC_DEBUG 63 /************************ MC SYSFS parts ***********************************/ 64 65 #define to_mci(k) container_of(k, struct mem_ctl_info, dev) 66 67 static ssize_t fsl_mc_inject_data_hi_show(struct device *dev, 68 struct device_attribute *mattr, 69 char *data) 70 { 71 struct mem_ctl_info *mci = to_mci(dev); 72 struct fsl_mc_pdata *pdata = mci->pvt_info; 73 return sprintf(data, "0x%08x", 74 ddr_in32(pdata, FSL_MC_DATA_ERR_INJECT_HI)); 75 } 76 77 static ssize_t fsl_mc_inject_data_lo_show(struct device *dev, 78 struct device_attribute *mattr, 79 char *data) 80 { 81 struct mem_ctl_info *mci = to_mci(dev); 82 struct fsl_mc_pdata *pdata = mci->pvt_info; 83 return sprintf(data, "0x%08x", 84 ddr_in32(pdata, FSL_MC_DATA_ERR_INJECT_LO)); 85 } 86 87 static ssize_t fsl_mc_inject_ctrl_show(struct device *dev, 88 struct device_attribute *mattr, 89 char *data) 90 { 91 struct mem_ctl_info *mci = to_mci(dev); 92 struct fsl_mc_pdata *pdata = mci->pvt_info; 93 return sprintf(data, "0x%08x", 94 ddr_in32(pdata, FSL_MC_ECC_ERR_INJECT)); 95 } 96 97 static ssize_t fsl_mc_inject_data_hi_store(struct device *dev, 98 struct device_attribute *mattr, 99 const char *data, size_t count) 100 { 101 struct mem_ctl_info *mci = to_mci(dev); 102 struct fsl_mc_pdata *pdata = mci->pvt_info; 103 unsigned long val; 104 int rc; 105 106 if (isdigit(*data)) { 107 rc = kstrtoul(data, 0, &val); 108 if (rc) 109 return rc; 110 111 ddr_out32(pdata, FSL_MC_DATA_ERR_INJECT_HI, val); 112 return count; 113 } 114 return 0; 115 } 116 117 static ssize_t fsl_mc_inject_data_lo_store(struct device *dev, 118 struct device_attribute *mattr, 119 const char *data, size_t count) 120 { 121 struct mem_ctl_info *mci = to_mci(dev); 122 struct fsl_mc_pdata *pdata = mci->pvt_info; 123 unsigned long val; 124 int rc; 125 126 if (isdigit(*data)) { 127 rc = kstrtoul(data, 0, &val); 128 if (rc) 129 return rc; 130 131 ddr_out32(pdata, FSL_MC_DATA_ERR_INJECT_LO, val); 132 return count; 133 } 134 return 0; 135 } 136 137 static ssize_t fsl_mc_inject_ctrl_store(struct device *dev, 138 struct device_attribute *mattr, 139 const char *data, size_t count) 140 { 141 struct mem_ctl_info *mci = to_mci(dev); 142 struct fsl_mc_pdata *pdata = mci->pvt_info; 143 unsigned long val; 144 int rc; 145 146 if (isdigit(*data)) { 147 rc = kstrtoul(data, 0, &val); 148 if (rc) 149 return rc; 150 151 ddr_out32(pdata, FSL_MC_ECC_ERR_INJECT, val); 152 return count; 153 } 154 return 0; 155 } 156 157 static DEVICE_ATTR(inject_data_hi, S_IRUGO | S_IWUSR, 158 fsl_mc_inject_data_hi_show, fsl_mc_inject_data_hi_store); 159 static DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR, 160 fsl_mc_inject_data_lo_show, fsl_mc_inject_data_lo_store); 161 static DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR, 162 fsl_mc_inject_ctrl_show, fsl_mc_inject_ctrl_store); 163 #endif /* CONFIG_EDAC_DEBUG */ 164 165 static struct attribute *fsl_ddr_dev_attrs[] = { 166 #ifdef CONFIG_EDAC_DEBUG 167 &dev_attr_inject_data_hi.attr, 168 &dev_attr_inject_data_lo.attr, 169 &dev_attr_inject_ctrl.attr, 170 #endif 171 NULL 172 }; 173 174 ATTRIBUTE_GROUPS(fsl_ddr_dev); 175 176 /**************************** MC Err device ***************************/ 177 178 /* 179 * Taken from table 8-55 in the MPC8641 User's Manual and/or 9-61 in the 180 * MPC8572 User's Manual. Each line represents a syndrome bit column as a 181 * 64-bit value, but split into an upper and lower 32-bit chunk. The labels 182 * below correspond to Freescale's manuals. 183 */ 184 static unsigned int ecc_table[16] = { 185 /* MSB LSB */ 186 /* [0:31] [32:63] */ 187 0xf00fe11e, 0xc33c0ff7, /* Syndrome bit 7 */ 188 0x00ff00ff, 0x00fff0ff, 189 0x0f0f0f0f, 0x0f0fff00, 190 0x11113333, 0x7777000f, 191 0x22224444, 0x8888222f, 192 0x44448888, 0xffff4441, 193 0x8888ffff, 0x11118882, 194 0xffff1111, 0x22221114, /* Syndrome bit 0 */ 195 }; 196 197 /* 198 * Calculate the correct ECC value for a 64-bit value specified by high:low 199 */ 200 static u8 calculate_ecc(u32 high, u32 low) 201 { 202 u32 mask_low; 203 u32 mask_high; 204 int bit_cnt; 205 u8 ecc = 0; 206 int i; 207 int j; 208 209 for (i = 0; i < 8; i++) { 210 mask_high = ecc_table[i * 2]; 211 mask_low = ecc_table[i * 2 + 1]; 212 bit_cnt = 0; 213 214 for (j = 0; j < 32; j++) { 215 if ((mask_high >> j) & 1) 216 bit_cnt ^= (high >> j) & 1; 217 if ((mask_low >> j) & 1) 218 bit_cnt ^= (low >> j) & 1; 219 } 220 221 ecc |= bit_cnt << i; 222 } 223 224 return ecc; 225 } 226 227 /* 228 * Create the syndrome code which is generated if the data line specified by 229 * 'bit' failed. Eg generate an 8-bit codes seen in Table 8-55 in the MPC8641 230 * User's Manual and 9-61 in the MPC8572 User's Manual. 231 */ 232 static u8 syndrome_from_bit(unsigned int bit) { 233 int i; 234 u8 syndrome = 0; 235 236 /* 237 * Cycle through the upper or lower 32-bit portion of each value in 238 * ecc_table depending on if 'bit' is in the upper or lower half of 239 * 64-bit data. 240 */ 241 for (i = bit < 32; i < 16; i += 2) 242 syndrome |= ((ecc_table[i] >> (bit % 32)) & 1) << (i / 2); 243 244 return syndrome; 245 } 246 247 /* 248 * Decode data and ecc syndrome to determine what went wrong 249 * Note: This can only decode single-bit errors 250 */ 251 static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc, 252 int *bad_data_bit, int *bad_ecc_bit) 253 { 254 int i; 255 u8 syndrome; 256 257 *bad_data_bit = -1; 258 *bad_ecc_bit = -1; 259 260 /* 261 * Calculate the ECC of the captured data and XOR it with the captured 262 * ECC to find an ECC syndrome value we can search for 263 */ 264 syndrome = calculate_ecc(cap_high, cap_low) ^ cap_ecc; 265 266 /* Check if a data line is stuck... */ 267 for (i = 0; i < 64; i++) { 268 if (syndrome == syndrome_from_bit(i)) { 269 *bad_data_bit = i; 270 return; 271 } 272 } 273 274 /* If data is correct, check ECC bits for errors... */ 275 for (i = 0; i < 8; i++) { 276 if ((syndrome >> i) & 0x1) { 277 *bad_ecc_bit = i; 278 return; 279 } 280 } 281 } 282 283 #define make64(high, low) (((u64)(high) << 32) | (low)) 284 285 static void fsl_mc_check(struct mem_ctl_info *mci) 286 { 287 struct fsl_mc_pdata *pdata = mci->pvt_info; 288 struct csrow_info *csrow; 289 u32 bus_width; 290 u32 err_detect; 291 u32 syndrome; 292 u64 err_addr; 293 u32 pfn; 294 int row_index; 295 u32 cap_high; 296 u32 cap_low; 297 int bad_data_bit; 298 int bad_ecc_bit; 299 300 err_detect = ddr_in32(pdata, FSL_MC_ERR_DETECT); 301 if (!err_detect) 302 return; 303 304 fsl_mc_printk(mci, KERN_ERR, "Err Detect Register: %#8.8x\n", 305 err_detect); 306 307 /* no more processing if not ECC bit errors */ 308 if (!(err_detect & (DDR_EDE_SBE | DDR_EDE_MBE))) { 309 ddr_out32(pdata, FSL_MC_ERR_DETECT, err_detect); 310 return; 311 } 312 313 syndrome = ddr_in32(pdata, FSL_MC_CAPTURE_ECC); 314 315 /* Mask off appropriate bits of syndrome based on bus width */ 316 bus_width = (ddr_in32(pdata, FSL_MC_DDR_SDRAM_CFG) & 317 DSC_DBW_MASK) ? 32 : 64; 318 if (bus_width == 64) 319 syndrome &= 0xff; 320 else 321 syndrome &= 0xffff; 322 323 err_addr = make64( 324 ddr_in32(pdata, FSL_MC_CAPTURE_EXT_ADDRESS), 325 ddr_in32(pdata, FSL_MC_CAPTURE_ADDRESS)); 326 pfn = err_addr >> PAGE_SHIFT; 327 328 for (row_index = 0; row_index < mci->nr_csrows; row_index++) { 329 csrow = mci->csrows[row_index]; 330 if ((pfn >= csrow->first_page) && (pfn <= csrow->last_page)) 331 break; 332 } 333 334 cap_high = ddr_in32(pdata, FSL_MC_CAPTURE_DATA_HI); 335 cap_low = ddr_in32(pdata, FSL_MC_CAPTURE_DATA_LO); 336 337 /* 338 * Analyze single-bit errors on 64-bit wide buses 339 * TODO: Add support for 32-bit wide buses 340 */ 341 if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) { 342 u64 cap = (u64)cap_high << 32 | cap_low; 343 u32 s = syndrome; 344 345 sbe_ecc_decode(cap_high, cap_low, syndrome, 346 &bad_data_bit, &bad_ecc_bit); 347 348 if (bad_data_bit >= 0) { 349 fsl_mc_printk(mci, KERN_ERR, "Faulty Data bit: %d\n", bad_data_bit); 350 cap ^= 1ULL << bad_data_bit; 351 } 352 353 if (bad_ecc_bit >= 0) { 354 fsl_mc_printk(mci, KERN_ERR, "Faulty ECC bit: %d\n", bad_ecc_bit); 355 s ^= 1 << bad_ecc_bit; 356 } 357 358 fsl_mc_printk(mci, KERN_ERR, 359 "Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n", 360 upper_32_bits(cap), lower_32_bits(cap), s); 361 } 362 363 fsl_mc_printk(mci, KERN_ERR, 364 "Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n", 365 cap_high, cap_low, syndrome); 366 fsl_mc_printk(mci, KERN_ERR, "Err addr: %#8.8llx\n", err_addr); 367 fsl_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn); 368 369 /* we are out of range */ 370 if (row_index == mci->nr_csrows) 371 fsl_mc_printk(mci, KERN_ERR, "PFN out of range!\n"); 372 373 if (err_detect & DDR_EDE_SBE) 374 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 375 pfn, err_addr & ~PAGE_MASK, syndrome, 376 row_index, 0, -1, 377 mci->ctl_name, ""); 378 379 if (err_detect & DDR_EDE_MBE) 380 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 381 pfn, err_addr & ~PAGE_MASK, syndrome, 382 row_index, 0, -1, 383 mci->ctl_name, ""); 384 385 ddr_out32(pdata, FSL_MC_ERR_DETECT, err_detect); 386 } 387 388 static irqreturn_t fsl_mc_isr(int irq, void *dev_id) 389 { 390 struct mem_ctl_info *mci = dev_id; 391 struct fsl_mc_pdata *pdata = mci->pvt_info; 392 u32 err_detect; 393 394 err_detect = ddr_in32(pdata, FSL_MC_ERR_DETECT); 395 if (!err_detect) 396 return IRQ_NONE; 397 398 fsl_mc_check(mci); 399 400 return IRQ_HANDLED; 401 } 402 403 static void fsl_ddr_init_csrows(struct mem_ctl_info *mci) 404 { 405 struct fsl_mc_pdata *pdata = mci->pvt_info; 406 struct csrow_info *csrow; 407 struct dimm_info *dimm; 408 u32 sdram_ctl; 409 u32 sdtype; 410 enum mem_type mtype; 411 u32 cs_bnds; 412 int index; 413 414 sdram_ctl = ddr_in32(pdata, FSL_MC_DDR_SDRAM_CFG); 415 416 sdtype = sdram_ctl & DSC_SDTYPE_MASK; 417 if (sdram_ctl & DSC_RD_EN) { 418 switch (sdtype) { 419 case 0x02000000: 420 mtype = MEM_RDDR; 421 break; 422 case 0x03000000: 423 mtype = MEM_RDDR2; 424 break; 425 case 0x07000000: 426 mtype = MEM_RDDR3; 427 break; 428 case 0x05000000: 429 mtype = MEM_RDDR4; 430 break; 431 default: 432 mtype = MEM_UNKNOWN; 433 break; 434 } 435 } else { 436 switch (sdtype) { 437 case 0x02000000: 438 mtype = MEM_DDR; 439 break; 440 case 0x03000000: 441 mtype = MEM_DDR2; 442 break; 443 case 0x07000000: 444 mtype = MEM_DDR3; 445 break; 446 case 0x05000000: 447 mtype = MEM_DDR4; 448 break; 449 case 0x04000000: 450 mtype = MEM_LPDDR4; 451 break; 452 default: 453 mtype = MEM_UNKNOWN; 454 break; 455 } 456 } 457 458 for (index = 0; index < mci->nr_csrows; index++) { 459 u32 start; 460 u32 end; 461 462 csrow = mci->csrows[index]; 463 dimm = csrow->channels[0]->dimm; 464 465 cs_bnds = ddr_in32(pdata, FSL_MC_CS_BNDS_0 + 466 (index * FSL_MC_CS_BNDS_OFS)); 467 468 start = (cs_bnds & 0xffff0000) >> 16; 469 end = (cs_bnds & 0x0000ffff); 470 471 if (start == end) 472 continue; /* not populated */ 473 474 start <<= (24 - PAGE_SHIFT); 475 end <<= (24 - PAGE_SHIFT); 476 end |= (1 << (24 - PAGE_SHIFT)) - 1; 477 478 csrow->first_page = start; 479 csrow->last_page = end; 480 481 dimm->nr_pages = end + 1 - start; 482 dimm->grain = 8; 483 dimm->mtype = mtype; 484 dimm->dtype = DEV_UNKNOWN; 485 if (pdata->flag == TYPE_IMX9) 486 dimm->dtype = DEV_X16; 487 else if (sdram_ctl & DSC_X32_EN) 488 dimm->dtype = DEV_X32; 489 dimm->edac_mode = EDAC_SECDED; 490 } 491 } 492 493 int fsl_mc_err_probe(struct platform_device *op) 494 { 495 struct mem_ctl_info *mci; 496 struct edac_mc_layer layers[2]; 497 struct fsl_mc_pdata *pdata; 498 struct resource r; 499 u32 ecc_en_mask; 500 u32 sdram_ctl; 501 int res; 502 503 if (!devres_open_group(&op->dev, fsl_mc_err_probe, GFP_KERNEL)) 504 return -ENOMEM; 505 506 layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; 507 layers[0].size = 4; 508 layers[0].is_virt_csrow = true; 509 layers[1].type = EDAC_MC_LAYER_CHANNEL; 510 layers[1].size = 1; 511 layers[1].is_virt_csrow = false; 512 mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, 513 sizeof(*pdata)); 514 if (!mci) { 515 devres_release_group(&op->dev, fsl_mc_err_probe); 516 return -ENOMEM; 517 } 518 519 pdata = mci->pvt_info; 520 pdata->name = "fsl_mc_err"; 521 mci->pdev = &op->dev; 522 pdata->edac_idx = edac_mc_idx++; 523 dev_set_drvdata(mci->pdev, mci); 524 mci->ctl_name = pdata->name; 525 mci->dev_name = pdata->name; 526 527 pdata->flag = (unsigned long)device_get_match_data(&op->dev); 528 529 /* 530 * Get the endianness of DDR controller registers. 531 * Default is big endian. 532 */ 533 pdata->little_endian = of_property_read_bool(op->dev.of_node, "little-endian"); 534 535 res = of_address_to_resource(op->dev.of_node, 0, &r); 536 if (res) { 537 pr_err("%s: Unable to get resource for MC err regs\n", 538 __func__); 539 goto err; 540 } 541 542 if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r), 543 pdata->name)) { 544 pr_err("%s: Error while requesting mem region\n", 545 __func__); 546 res = -EBUSY; 547 goto err; 548 } 549 550 pdata->mc_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r)); 551 if (!pdata->mc_vbase) { 552 pr_err("%s: Unable to setup MC err regs\n", __func__); 553 res = -ENOMEM; 554 goto err; 555 } 556 557 if (pdata->flag == TYPE_IMX9) { 558 pdata->inject_vbase = devm_platform_ioremap_resource_byname(op, "inject"); 559 if (IS_ERR(pdata->inject_vbase)) { 560 res = -ENOMEM; 561 goto err; 562 } 563 } 564 565 if (pdata->flag == TYPE_IMX9) { 566 sdram_ctl = ddr_in32(pdata, IMX9_MC_ERR_EN); 567 ecc_en_mask = ERR_ECC_EN | ERR_INLINE_ECC; 568 } else { 569 sdram_ctl = ddr_in32(pdata, FSL_MC_DDR_SDRAM_CFG); 570 ecc_en_mask = DSC_ECC_EN; 571 } 572 573 if ((sdram_ctl & ecc_en_mask) != ecc_en_mask) { 574 /* no ECC */ 575 pr_warn("%s: No ECC DIMMs discovered\n", __func__); 576 res = -ENODEV; 577 goto err; 578 } 579 580 edac_dbg(3, "init mci\n"); 581 mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR | 582 MEM_FLAG_DDR2 | MEM_FLAG_RDDR2 | 583 MEM_FLAG_DDR3 | MEM_FLAG_RDDR3 | 584 MEM_FLAG_DDR4 | MEM_FLAG_RDDR4 | 585 MEM_FLAG_LPDDR4; 586 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; 587 mci->edac_cap = EDAC_FLAG_SECDED; 588 mci->mod_name = EDAC_MOD_STR; 589 590 if (edac_op_state == EDAC_OPSTATE_POLL) 591 mci->edac_check = fsl_mc_check; 592 593 mci->ctl_page_to_phys = NULL; 594 595 mci->scrub_mode = SCRUB_SW_SRC; 596 597 fsl_ddr_init_csrows(mci); 598 599 /* store the original error disable bits */ 600 pdata->orig_ddr_err_disable = ddr_in32(pdata, FSL_MC_ERR_DISABLE); 601 ddr_out32(pdata, FSL_MC_ERR_DISABLE, 0); 602 603 /* clear all error bits */ 604 ddr_out32(pdata, FSL_MC_ERR_DETECT, ~0); 605 606 res = edac_mc_add_mc_with_groups(mci, fsl_ddr_dev_groups); 607 if (res) { 608 edac_dbg(3, "failed edac_mc_add_mc()\n"); 609 goto err; 610 } 611 612 if (edac_op_state == EDAC_OPSTATE_INT) { 613 ddr_out32(pdata, FSL_MC_ERR_INT_EN, 614 DDR_EIE_MBEE | DDR_EIE_SBEE); 615 616 /* store the original error management threshold */ 617 pdata->orig_ddr_err_sbe = ddr_in32(pdata, 618 FSL_MC_ERR_SBE) & 0xff0000; 619 620 /* set threshold to 1 error per interrupt */ 621 ddr_out32(pdata, FSL_MC_ERR_SBE, 0x10000); 622 623 /* register interrupts */ 624 pdata->irq = platform_get_irq(op, 0); 625 res = devm_request_irq(&op->dev, pdata->irq, 626 fsl_mc_isr, 627 IRQF_SHARED, 628 "[EDAC] MC err", mci); 629 if (res < 0) { 630 pr_err("%s: Unable to request irq %d for FSL DDR DRAM ERR\n", 631 __func__, pdata->irq); 632 res = -ENODEV; 633 goto err2; 634 } 635 636 pr_info(EDAC_MOD_STR " acquired irq %d for MC\n", 637 pdata->irq); 638 } 639 640 devres_remove_group(&op->dev, fsl_mc_err_probe); 641 edac_dbg(3, "success\n"); 642 pr_info(EDAC_MOD_STR " MC err registered\n"); 643 644 return 0; 645 646 err2: 647 edac_mc_del_mc(&op->dev); 648 err: 649 devres_release_group(&op->dev, fsl_mc_err_probe); 650 edac_mc_free(mci); 651 return res; 652 } 653 654 void fsl_mc_err_remove(struct platform_device *op) 655 { 656 struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); 657 struct fsl_mc_pdata *pdata = mci->pvt_info; 658 659 edac_dbg(0, "\n"); 660 661 if (edac_op_state == EDAC_OPSTATE_INT) { 662 ddr_out32(pdata, FSL_MC_ERR_INT_EN, 0); 663 } 664 665 ddr_out32(pdata, FSL_MC_ERR_DISABLE, 666 pdata->orig_ddr_err_disable); 667 ddr_out32(pdata, FSL_MC_ERR_SBE, pdata->orig_ddr_err_sbe); 668 669 670 edac_mc_del_mc(&op->dev); 671 edac_mc_free(mci); 672 } 673