1/* 2 * Marvell MV64x60 Memory Controller kernel module for PPC platforms 3 * 4 * Author: Dave Jiang <djiang@mvista.com> 5 * 6 * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under 7 * the terms of the GNU General Public License version 2. This program 8 * is licensed "as is" without any warranty of any kind, whether express 9 * or implied. 10 * 11 */ 12 13#include <linux/module.h> 14#include <linux/init.h> 15#include <linux/interrupt.h> 16#include <linux/io.h> 17#include <linux/edac.h> 18#include <linux/gfp.h> 19 20#include "edac_core.h" 21#include "edac_module.h" 22#include "mv64x60_edac.h" 23 24static const char *mv64x60_ctl_name = "MV64x60"; 25static int edac_dev_idx; 26static int edac_pci_idx; 27static int edac_mc_idx; 28 29/*********************** PCI err device **********************************/ 30#ifdef CONFIG_PCI 31static void mv64x60_pci_check(struct edac_pci_ctl_info *pci) 32{ 33 struct mv64x60_pci_pdata *pdata = pci->pvt_info; 34 u32 cause; 35 36 cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); 37 if (!cause) 38 return; 39 40 printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose); 41 printk(KERN_ERR "Cause register: 0x%08x\n", cause); 42 printk(KERN_ERR "Address Low: 0x%08x\n", 43 in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO)); 44 printk(KERN_ERR "Address High: 0x%08x\n", 45 in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI)); 46 printk(KERN_ERR "Attribute: 0x%08x\n", 47 in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR)); 48 printk(KERN_ERR "Command: 0x%08x\n", 49 in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD)); 50 out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause); 51 52 if (cause & MV64X60_PCI_PE_MASK) 53 edac_pci_handle_pe(pci, pci->ctl_name); 54 55 if (!(cause & MV64X60_PCI_PE_MASK)) 56 edac_pci_handle_npe(pci, pci->ctl_name); 57} 58 59static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id) 60{ 61 struct edac_pci_ctl_info *pci = dev_id; 62 struct mv64x60_pci_pdata *pdata = pci->pvt_info; 63 u32 val; 64 65 val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); 66 if (!val) 67 return IRQ_NONE; 68 69 mv64x60_pci_check(pci); 70 71 return IRQ_HANDLED; 72} 73 74/* 75 * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of 76 * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as 77 * well. IOW, don't set bit 0. 78 */ 79 80/* Erratum FEr PCI-#16: clear bit 0 of PCI SERRn Mask reg. */ 81static int __init mv64x60_pci_fixup(struct platform_device *pdev) 82{ 83 struct resource *r; 84 void __iomem *pci_serr; 85 86 r = platform_get_resource(pdev, IORESOURCE_MEM, 1); 87 if (!r) { 88 printk(KERN_ERR "%s: Unable to get resource for " 89 "PCI err regs\n", __func__); 90 return -ENOENT; 91 } 92 93 pci_serr = ioremap(r->start, resource_size(r)); 94 if (!pci_serr) 95 return -ENOMEM; 96 97 out_le32(pci_serr, in_le32(pci_serr) & ~0x1); 98 iounmap(pci_serr); 99 100 return 0; 101} 102 103static int mv64x60_pci_err_probe(struct platform_device *pdev) 104{ 105 struct edac_pci_ctl_info *pci; 106 struct mv64x60_pci_pdata *pdata; 107 struct resource *r; 108 int res = 0; 109 110 if (!devres_open_group(&pdev->dev, mv64x60_pci_err_probe, GFP_KERNEL)) 111 return -ENOMEM; 112 113 pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mv64x60_pci_err"); 114 if (!pci) 115 return -ENOMEM; 116 117 pdata = pci->pvt_info; 118 119 pdata->pci_hose = pdev->id; 120 pdata->name = "mpc85xx_pci_err"; 121 pdata->irq = NO_IRQ; 122 platform_set_drvdata(pdev, pci); 123 pci->dev = &pdev->dev; 124 pci->dev_name = dev_name(&pdev->dev); 125 pci->mod_name = EDAC_MOD_STR; 126 pci->ctl_name = pdata->name; 127 128 if (edac_op_state == EDAC_OPSTATE_POLL) 129 pci->edac_check = mv64x60_pci_check; 130 131 pdata->edac_idx = edac_pci_idx++; 132 133 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 134 if (!r) { 135 printk(KERN_ERR "%s: Unable to get resource for " 136 "PCI err regs\n", __func__); 137 res = -ENOENT; 138 goto err; 139 } 140 141 if (!devm_request_mem_region(&pdev->dev, 142 r->start, 143 resource_size(r), 144 pdata->name)) { 145 printk(KERN_ERR "%s: Error while requesting mem region\n", 146 __func__); 147 res = -EBUSY; 148 goto err; 149 } 150 151 pdata->pci_vbase = devm_ioremap(&pdev->dev, 152 r->start, 153 resource_size(r)); 154 if (!pdata->pci_vbase) { 155 printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); 156 res = -ENOMEM; 157 goto err; 158 } 159 160 res = mv64x60_pci_fixup(pdev); 161 if (res < 0) { 162 printk(KERN_ERR "%s: PCI fixup failed\n", __func__); 163 goto err; 164 } 165 166 out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0); 167 out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0); 168 out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 169 MV64X60_PCIx_ERR_MASK_VAL); 170 171 if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { 172 edac_dbg(3, "failed edac_pci_add_device()\n"); 173 goto err; 174 } 175 176 if (edac_op_state == EDAC_OPSTATE_INT) { 177 pdata->irq = platform_get_irq(pdev, 0); 178 res = devm_request_irq(&pdev->dev, 179 pdata->irq, 180 mv64x60_pci_isr, 181 0, 182 "[EDAC] PCI err", 183 pci); 184 if (res < 0) { 185 printk(KERN_ERR "%s: Unable to request irq %d for " 186 "MV64x60 PCI ERR\n", __func__, pdata->irq); 187 res = -ENODEV; 188 goto err2; 189 } 190 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n", 191 pdata->irq); 192 } 193 194 devres_remove_group(&pdev->dev, mv64x60_pci_err_probe); 195 196 /* get this far and it's successful */ 197 edac_dbg(3, "success\n"); 198 199 return 0; 200 201err2: 202 edac_pci_del_device(&pdev->dev); 203err: 204 edac_pci_free_ctl_info(pci); 205 devres_release_group(&pdev->dev, mv64x60_pci_err_probe); 206 return res; 207} 208 209static int mv64x60_pci_err_remove(struct platform_device *pdev) 210{ 211 struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); 212 213 edac_dbg(0, "\n"); 214 215 edac_pci_del_device(&pdev->dev); 216 217 edac_pci_free_ctl_info(pci); 218 219 return 0; 220} 221 222static struct platform_driver mv64x60_pci_err_driver = { 223 .probe = mv64x60_pci_err_probe, 224 .remove = mv64x60_pci_err_remove, 225 .driver = { 226 .name = "mv64x60_pci_err", 227 } 228}; 229 230#endif /* CONFIG_PCI */ 231 232/*********************** SRAM err device **********************************/ 233static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev) 234{ 235 struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; 236 u32 cause; 237 238 cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); 239 if (!cause) 240 return; 241 242 printk(KERN_ERR "Error in internal SRAM\n"); 243 printk(KERN_ERR "Cause register: 0x%08x\n", cause); 244 printk(KERN_ERR "Address Low: 0x%08x\n", 245 in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO)); 246 printk(KERN_ERR "Address High: 0x%08x\n", 247 in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI)); 248 printk(KERN_ERR "Data Low: 0x%08x\n", 249 in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO)); 250 printk(KERN_ERR "Data High: 0x%08x\n", 251 in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI)); 252 printk(KERN_ERR "Parity: 0x%08x\n", 253 in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY)); 254 out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); 255 256 edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); 257} 258 259static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id) 260{ 261 struct edac_device_ctl_info *edac_dev = dev_id; 262 struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; 263 u32 cause; 264 265 cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); 266 if (!cause) 267 return IRQ_NONE; 268 269 mv64x60_sram_check(edac_dev); 270 271 return IRQ_HANDLED; 272} 273 274static int mv64x60_sram_err_probe(struct platform_device *pdev) 275{ 276 struct edac_device_ctl_info *edac_dev; 277 struct mv64x60_sram_pdata *pdata; 278 struct resource *r; 279 int res = 0; 280 281 if (!devres_open_group(&pdev->dev, mv64x60_sram_err_probe, GFP_KERNEL)) 282 return -ENOMEM; 283 284 edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata), 285 "sram", 1, NULL, 0, 0, NULL, 0, 286 edac_dev_idx); 287 if (!edac_dev) { 288 devres_release_group(&pdev->dev, mv64x60_sram_err_probe); 289 return -ENOMEM; 290 } 291 292 pdata = edac_dev->pvt_info; 293 pdata->name = "mv64x60_sram_err"; 294 pdata->irq = NO_IRQ; 295 edac_dev->dev = &pdev->dev; 296 platform_set_drvdata(pdev, edac_dev); 297 edac_dev->dev_name = dev_name(&pdev->dev); 298 299 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 300 if (!r) { 301 printk(KERN_ERR "%s: Unable to get resource for " 302 "SRAM err regs\n", __func__); 303 res = -ENOENT; 304 goto err; 305 } 306 307 if (!devm_request_mem_region(&pdev->dev, 308 r->start, 309 resource_size(r), 310 pdata->name)) { 311 printk(KERN_ERR "%s: Error while request mem region\n", 312 __func__); 313 res = -EBUSY; 314 goto err; 315 } 316 317 pdata->sram_vbase = devm_ioremap(&pdev->dev, 318 r->start, 319 resource_size(r)); 320 if (!pdata->sram_vbase) { 321 printk(KERN_ERR "%s: Unable to setup SRAM err regs\n", 322 __func__); 323 res = -ENOMEM; 324 goto err; 325 } 326 327 /* setup SRAM err registers */ 328 out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); 329 330 edac_dev->mod_name = EDAC_MOD_STR; 331 edac_dev->ctl_name = pdata->name; 332 333 if (edac_op_state == EDAC_OPSTATE_POLL) 334 edac_dev->edac_check = mv64x60_sram_check; 335 336 pdata->edac_idx = edac_dev_idx++; 337 338 if (edac_device_add_device(edac_dev) > 0) { 339 edac_dbg(3, "failed edac_device_add_device()\n"); 340 goto err; 341 } 342 343 if (edac_op_state == EDAC_OPSTATE_INT) { 344 pdata->irq = platform_get_irq(pdev, 0); 345 res = devm_request_irq(&pdev->dev, 346 pdata->irq, 347 mv64x60_sram_isr, 348 0, 349 "[EDAC] SRAM err", 350 edac_dev); 351 if (res < 0) { 352 printk(KERN_ERR 353 "%s: Unable to request irq %d for " 354 "MV64x60 SRAM ERR\n", __func__, pdata->irq); 355 res = -ENODEV; 356 goto err2; 357 } 358 359 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for SRAM Err\n", 360 pdata->irq); 361 } 362 363 devres_remove_group(&pdev->dev, mv64x60_sram_err_probe); 364 365 /* get this far and it's successful */ 366 edac_dbg(3, "success\n"); 367 368 return 0; 369 370err2: 371 edac_device_del_device(&pdev->dev); 372err: 373 devres_release_group(&pdev->dev, mv64x60_sram_err_probe); 374 edac_device_free_ctl_info(edac_dev); 375 return res; 376} 377 378static int mv64x60_sram_err_remove(struct platform_device *pdev) 379{ 380 struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); 381 382 edac_dbg(0, "\n"); 383 384 edac_device_del_device(&pdev->dev); 385 edac_device_free_ctl_info(edac_dev); 386 387 return 0; 388} 389 390static struct platform_driver mv64x60_sram_err_driver = { 391 .probe = mv64x60_sram_err_probe, 392 .remove = mv64x60_sram_err_remove, 393 .driver = { 394 .name = "mv64x60_sram_err", 395 } 396}; 397 398/*********************** CPU err device **********************************/ 399static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev) 400{ 401 struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; 402 u32 cause; 403 404 cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & 405 MV64x60_CPU_CAUSE_MASK; 406 if (!cause) 407 return; 408 409 printk(KERN_ERR "Error on CPU interface\n"); 410 printk(KERN_ERR "Cause register: 0x%08x\n", cause); 411 printk(KERN_ERR "Address Low: 0x%08x\n", 412 in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO)); 413 printk(KERN_ERR "Address High: 0x%08x\n", 414 in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI)); 415 printk(KERN_ERR "Data Low: 0x%08x\n", 416 in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO)); 417 printk(KERN_ERR "Data High: 0x%08x\n", 418 in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI)); 419 printk(KERN_ERR "Parity: 0x%08x\n", 420 in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY)); 421 out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); 422 423 edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); 424} 425 426static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id) 427{ 428 struct edac_device_ctl_info *edac_dev = dev_id; 429 struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; 430 u32 cause; 431 432 cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & 433 MV64x60_CPU_CAUSE_MASK; 434 if (!cause) 435 return IRQ_NONE; 436 437 mv64x60_cpu_check(edac_dev); 438 439 return IRQ_HANDLED; 440} 441 442static int mv64x60_cpu_err_probe(struct platform_device *pdev) 443{ 444 struct edac_device_ctl_info *edac_dev; 445 struct resource *r; 446 struct mv64x60_cpu_pdata *pdata; 447 int res = 0; 448 449 if (!devres_open_group(&pdev->dev, mv64x60_cpu_err_probe, GFP_KERNEL)) 450 return -ENOMEM; 451 452 edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata), 453 "cpu", 1, NULL, 0, 0, NULL, 0, 454 edac_dev_idx); 455 if (!edac_dev) { 456 devres_release_group(&pdev->dev, mv64x60_cpu_err_probe); 457 return -ENOMEM; 458 } 459 460 pdata = edac_dev->pvt_info; 461 pdata->name = "mv64x60_cpu_err"; 462 pdata->irq = NO_IRQ; 463 edac_dev->dev = &pdev->dev; 464 platform_set_drvdata(pdev, edac_dev); 465 edac_dev->dev_name = dev_name(&pdev->dev); 466 467 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 468 if (!r) { 469 printk(KERN_ERR "%s: Unable to get resource for " 470 "CPU err regs\n", __func__); 471 res = -ENOENT; 472 goto err; 473 } 474 475 if (!devm_request_mem_region(&pdev->dev, 476 r->start, 477 resource_size(r), 478 pdata->name)) { 479 printk(KERN_ERR "%s: Error while requesting mem region\n", 480 __func__); 481 res = -EBUSY; 482 goto err; 483 } 484 485 pdata->cpu_vbase[0] = devm_ioremap(&pdev->dev, 486 r->start, 487 resource_size(r)); 488 if (!pdata->cpu_vbase[0]) { 489 printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__); 490 res = -ENOMEM; 491 goto err; 492 } 493 494 r = platform_get_resource(pdev, IORESOURCE_MEM, 1); 495 if (!r) { 496 printk(KERN_ERR "%s: Unable to get resource for " 497 "CPU err regs\n", __func__); 498 res = -ENOENT; 499 goto err; 500 } 501 502 if (!devm_request_mem_region(&pdev->dev, 503 r->start, 504 resource_size(r), 505 pdata->name)) { 506 printk(KERN_ERR "%s: Error while requesting mem region\n", 507 __func__); 508 res = -EBUSY; 509 goto err; 510 } 511 512 pdata->cpu_vbase[1] = devm_ioremap(&pdev->dev, 513 r->start, 514 resource_size(r)); 515 if (!pdata->cpu_vbase[1]) { 516 printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__); 517 res = -ENOMEM; 518 goto err; 519 } 520 521 /* setup CPU err registers */ 522 out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); 523 out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0); 524 out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff); 525 526 edac_dev->mod_name = EDAC_MOD_STR; 527 edac_dev->ctl_name = pdata->name; 528 if (edac_op_state == EDAC_OPSTATE_POLL) 529 edac_dev->edac_check = mv64x60_cpu_check; 530 531 pdata->edac_idx = edac_dev_idx++; 532 533 if (edac_device_add_device(edac_dev) > 0) { 534 edac_dbg(3, "failed edac_device_add_device()\n"); 535 goto err; 536 } 537 538 if (edac_op_state == EDAC_OPSTATE_INT) { 539 pdata->irq = platform_get_irq(pdev, 0); 540 res = devm_request_irq(&pdev->dev, 541 pdata->irq, 542 mv64x60_cpu_isr, 543 0, 544 "[EDAC] CPU err", 545 edac_dev); 546 if (res < 0) { 547 printk(KERN_ERR 548 "%s: Unable to request irq %d for MV64x60 " 549 "CPU ERR\n", __func__, pdata->irq); 550 res = -ENODEV; 551 goto err2; 552 } 553 554 printk(KERN_INFO EDAC_MOD_STR 555 " acquired irq %d for CPU Err\n", pdata->irq); 556 } 557 558 devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe); 559 560 /* get this far and it's successful */ 561 edac_dbg(3, "success\n"); 562 563 return 0; 564 565err2: 566 edac_device_del_device(&pdev->dev); 567err: 568 devres_release_group(&pdev->dev, mv64x60_cpu_err_probe); 569 edac_device_free_ctl_info(edac_dev); 570 return res; 571} 572 573static int mv64x60_cpu_err_remove(struct platform_device *pdev) 574{ 575 struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); 576 577 edac_dbg(0, "\n"); 578 579 edac_device_del_device(&pdev->dev); 580 edac_device_free_ctl_info(edac_dev); 581 return 0; 582} 583 584static struct platform_driver mv64x60_cpu_err_driver = { 585 .probe = mv64x60_cpu_err_probe, 586 .remove = mv64x60_cpu_err_remove, 587 .driver = { 588 .name = "mv64x60_cpu_err", 589 } 590}; 591 592/*********************** DRAM err device **********************************/ 593 594static void mv64x60_mc_check(struct mem_ctl_info *mci) 595{ 596 struct mv64x60_mc_pdata *pdata = mci->pvt_info; 597 u32 reg; 598 u32 err_addr; 599 u32 sdram_ecc; 600 u32 comp_ecc; 601 u32 syndrome; 602 603 reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); 604 if (!reg) 605 return; 606 607 err_addr = reg & ~0x3; 608 sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD); 609 comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC); 610 syndrome = sdram_ecc ^ comp_ecc; 611 612 /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */ 613 if (!(reg & 0x1)) 614 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 615 err_addr >> PAGE_SHIFT, 616 err_addr & PAGE_MASK, syndrome, 617 0, 0, -1, 618 mci->ctl_name, ""); 619 else /* 2 bit error, UE */ 620 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 621 err_addr >> PAGE_SHIFT, 622 err_addr & PAGE_MASK, 0, 623 0, 0, -1, 624 mci->ctl_name, ""); 625 626 /* clear the error */ 627 out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); 628} 629 630static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id) 631{ 632 struct mem_ctl_info *mci = dev_id; 633 struct mv64x60_mc_pdata *pdata = mci->pvt_info; 634 u32 reg; 635 636 reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); 637 if (!reg) 638 return IRQ_NONE; 639 640 /* writing 0's to the ECC err addr in check function clears irq */ 641 mv64x60_mc_check(mci); 642 643 return IRQ_HANDLED; 644} 645 646static void get_total_mem(struct mv64x60_mc_pdata *pdata) 647{ 648 struct device_node *np = NULL; 649 const unsigned int *reg; 650 651 np = of_find_node_by_type(NULL, "memory"); 652 if (!np) 653 return; 654 655 reg = of_get_property(np, "reg", NULL); 656 657 pdata->total_mem = reg[1]; 658} 659 660static void mv64x60_init_csrows(struct mem_ctl_info *mci, 661 struct mv64x60_mc_pdata *pdata) 662{ 663 struct csrow_info *csrow; 664 struct dimm_info *dimm; 665 666 u32 devtype; 667 u32 ctl; 668 669 get_total_mem(pdata); 670 671 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); 672 673 csrow = mci->csrows[0]; 674 dimm = csrow->channels[0]->dimm; 675 676 dimm->nr_pages = pdata->total_mem >> PAGE_SHIFT; 677 dimm->grain = 8; 678 679 dimm->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR; 680 681 devtype = (ctl >> 20) & 0x3; 682 switch (devtype) { 683 case 0x0: 684 dimm->dtype = DEV_X32; 685 break; 686 case 0x2: /* could be X8 too, but no way to tell */ 687 dimm->dtype = DEV_X16; 688 break; 689 case 0x3: 690 dimm->dtype = DEV_X4; 691 break; 692 default: 693 dimm->dtype = DEV_UNKNOWN; 694 break; 695 } 696 697 dimm->edac_mode = EDAC_SECDED; 698} 699 700static int mv64x60_mc_err_probe(struct platform_device *pdev) 701{ 702 struct mem_ctl_info *mci; 703 struct edac_mc_layer layers[2]; 704 struct mv64x60_mc_pdata *pdata; 705 struct resource *r; 706 u32 ctl; 707 int res = 0; 708 709 if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL)) 710 return -ENOMEM; 711 712 layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; 713 layers[0].size = 1; 714 layers[0].is_virt_csrow = true; 715 layers[1].type = EDAC_MC_LAYER_CHANNEL; 716 layers[1].size = 1; 717 layers[1].is_virt_csrow = false; 718 mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, 719 sizeof(struct mv64x60_mc_pdata)); 720 if (!mci) { 721 printk(KERN_ERR "%s: No memory for CPU err\n", __func__); 722 devres_release_group(&pdev->dev, mv64x60_mc_err_probe); 723 return -ENOMEM; 724 } 725 726 pdata = mci->pvt_info; 727 mci->pdev = &pdev->dev; 728 platform_set_drvdata(pdev, mci); 729 pdata->name = "mv64x60_mc_err"; 730 pdata->irq = NO_IRQ; 731 mci->dev_name = dev_name(&pdev->dev); 732 pdata->edac_idx = edac_mc_idx++; 733 734 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 735 if (!r) { 736 printk(KERN_ERR "%s: Unable to get resource for " 737 "MC err regs\n", __func__); 738 res = -ENOENT; 739 goto err; 740 } 741 742 if (!devm_request_mem_region(&pdev->dev, 743 r->start, 744 resource_size(r), 745 pdata->name)) { 746 printk(KERN_ERR "%s: Error while requesting mem region\n", 747 __func__); 748 res = -EBUSY; 749 goto err; 750 } 751 752 pdata->mc_vbase = devm_ioremap(&pdev->dev, 753 r->start, 754 resource_size(r)); 755 if (!pdata->mc_vbase) { 756 printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__); 757 res = -ENOMEM; 758 goto err; 759 } 760 761 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); 762 if (!(ctl & MV64X60_SDRAM_ECC)) { 763 /* Non-ECC RAM? */ 764 printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__); 765 res = -ENODEV; 766 goto err2; 767 } 768 769 edac_dbg(3, "init mci\n"); 770 mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; 771 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; 772 mci->edac_cap = EDAC_FLAG_SECDED; 773 mci->mod_name = EDAC_MOD_STR; 774 mci->mod_ver = MV64x60_REVISION; 775 mci->ctl_name = mv64x60_ctl_name; 776 777 if (edac_op_state == EDAC_OPSTATE_POLL) 778 mci->edac_check = mv64x60_mc_check; 779 780 mci->ctl_page_to_phys = NULL; 781 782 mci->scrub_mode = SCRUB_SW_SRC; 783 784 mv64x60_init_csrows(mci, pdata); 785 786 /* setup MC registers */ 787 out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); 788 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL); 789 ctl = (ctl & 0xff00ffff) | 0x10000; 790 out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); 791 792 res = edac_mc_add_mc(mci); 793 if (res) { 794 edac_dbg(3, "failed edac_mc_add_mc()\n"); 795 goto err; 796 } 797 798 if (edac_op_state == EDAC_OPSTATE_INT) { 799 /* acquire interrupt that reports errors */ 800 pdata->irq = platform_get_irq(pdev, 0); 801 res = devm_request_irq(&pdev->dev, 802 pdata->irq, 803 mv64x60_mc_isr, 804 0, 805 "[EDAC] MC err", 806 mci); 807 if (res < 0) { 808 printk(KERN_ERR "%s: Unable to request irq %d for " 809 "MV64x60 DRAM ERR\n", __func__, pdata->irq); 810 res = -ENODEV; 811 goto err2; 812 } 813 814 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n", 815 pdata->irq); 816 } 817 818 /* get this far and it's successful */ 819 edac_dbg(3, "success\n"); 820 821 return 0; 822 823err2: 824 edac_mc_del_mc(&pdev->dev); 825err: 826 devres_release_group(&pdev->dev, mv64x60_mc_err_probe); 827 edac_mc_free(mci); 828 return res; 829} 830 831static int mv64x60_mc_err_remove(struct platform_device *pdev) 832{ 833 struct mem_ctl_info *mci = platform_get_drvdata(pdev); 834 835 edac_dbg(0, "\n"); 836 837 edac_mc_del_mc(&pdev->dev); 838 edac_mc_free(mci); 839 return 0; 840} 841 842static struct platform_driver mv64x60_mc_err_driver = { 843 .probe = mv64x60_mc_err_probe, 844 .remove = mv64x60_mc_err_remove, 845 .driver = { 846 .name = "mv64x60_mc_err", 847 } 848}; 849 850static int __init mv64x60_edac_init(void) 851{ 852 int ret = 0; 853 854 printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n"); 855 printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n"); 856 /* make sure error reporting method is sane */ 857 switch (edac_op_state) { 858 case EDAC_OPSTATE_POLL: 859 case EDAC_OPSTATE_INT: 860 break; 861 default: 862 edac_op_state = EDAC_OPSTATE_INT; 863 break; 864 } 865 866 ret = platform_driver_register(&mv64x60_mc_err_driver); 867 if (ret) 868 printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n"); 869 870 ret = platform_driver_register(&mv64x60_cpu_err_driver); 871 if (ret) 872 printk(KERN_WARNING EDAC_MOD_STR 873 "CPU err failed to register\n"); 874 875 ret = platform_driver_register(&mv64x60_sram_err_driver); 876 if (ret) 877 printk(KERN_WARNING EDAC_MOD_STR 878 "SRAM err failed to register\n"); 879 880#ifdef CONFIG_PCI 881 ret = platform_driver_register(&mv64x60_pci_err_driver); 882 if (ret) 883 printk(KERN_WARNING EDAC_MOD_STR 884 "PCI err failed to register\n"); 885#endif 886 887 return ret; 888} 889module_init(mv64x60_edac_init); 890 891static void __exit mv64x60_edac_exit(void) 892{ 893#ifdef CONFIG_PCI 894 platform_driver_unregister(&mv64x60_pci_err_driver); 895#endif 896 platform_driver_unregister(&mv64x60_sram_err_driver); 897 platform_driver_unregister(&mv64x60_cpu_err_driver); 898 platform_driver_unregister(&mv64x60_mc_err_driver); 899} 900module_exit(mv64x60_edac_exit); 901 902MODULE_LICENSE("GPL"); 903MODULE_AUTHOR("Montavista Software, Inc."); 904module_param(edac_op_state, int, 0444); 905MODULE_PARM_DESC(edac_op_state, 906 "EDAC Error Reporting state: 0=Poll, 2=Interrupt"); 907