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 __devinit 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 debugf3("%s(): failed edac_pci_add_device()\n", __func__); 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 IRQF_DISABLED, 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 debugf3("%s(): success\n", __func__); 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 debugf0("%s()\n", __func__); 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 = __devexit_p(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 __devinit 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 debugf3("%s(): failed edac_device_add_device()\n", __func__); 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 IRQF_DISABLED, 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 debugf3("%s(): success\n", __func__); 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 debugf0("%s()\n", __func__); 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 __devinit 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 debugf3("%s(): failed edac_device_add_device()\n", __func__); 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 IRQF_DISABLED, 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 debugf3("%s(): success\n", __func__); 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 debugf0("%s()\n", __func__); 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_ce(mci, err_addr >> PAGE_SHIFT, 615 err_addr & PAGE_MASK, syndrome, 0, 0, 616 mci->ctl_name); 617 else /* 2 bit error, UE */ 618 edac_mc_handle_ue(mci, err_addr >> PAGE_SHIFT, 619 err_addr & PAGE_MASK, 0, mci->ctl_name); 620 621 /* clear the error */ 622 out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); 623} 624 625static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id) 626{ 627 struct mem_ctl_info *mci = dev_id; 628 struct mv64x60_mc_pdata *pdata = mci->pvt_info; 629 u32 reg; 630 631 reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); 632 if (!reg) 633 return IRQ_NONE; 634 635 /* writing 0's to the ECC err addr in check function clears irq */ 636 mv64x60_mc_check(mci); 637 638 return IRQ_HANDLED; 639} 640 641static void get_total_mem(struct mv64x60_mc_pdata *pdata) 642{ 643 struct device_node *np = NULL; 644 const unsigned int *reg; 645 646 np = of_find_node_by_type(NULL, "memory"); 647 if (!np) 648 return; 649 650 reg = of_get_property(np, "reg", NULL); 651 652 pdata->total_mem = reg[1]; 653} 654 655static void mv64x60_init_csrows(struct mem_ctl_info *mci, 656 struct mv64x60_mc_pdata *pdata) 657{ 658 struct csrow_info *csrow; 659 u32 devtype; 660 u32 ctl; 661 662 get_total_mem(pdata); 663 664 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); 665 666 csrow = &mci->csrows[0]; 667 csrow->first_page = 0; 668 csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT; 669 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 670 csrow->grain = 8; 671 672 csrow->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR; 673 674 devtype = (ctl >> 20) & 0x3; 675 switch (devtype) { 676 case 0x0: 677 csrow->dtype = DEV_X32; 678 break; 679 case 0x2: /* could be X8 too, but no way to tell */ 680 csrow->dtype = DEV_X16; 681 break; 682 case 0x3: 683 csrow->dtype = DEV_X4; 684 break; 685 default: 686 csrow->dtype = DEV_UNKNOWN; 687 break; 688 } 689 690 csrow->edac_mode = EDAC_SECDED; 691} 692 693static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) 694{ 695 struct mem_ctl_info *mci; 696 struct mv64x60_mc_pdata *pdata; 697 struct resource *r; 698 u32 ctl; 699 int res = 0; 700 701 if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL)) 702 return -ENOMEM; 703 704 mci = edac_mc_alloc(sizeof(struct mv64x60_mc_pdata), 1, 1, edac_mc_idx); 705 if (!mci) { 706 printk(KERN_ERR "%s: No memory for CPU err\n", __func__); 707 devres_release_group(&pdev->dev, mv64x60_mc_err_probe); 708 return -ENOMEM; 709 } 710 711 pdata = mci->pvt_info; 712 mci->dev = &pdev->dev; 713 platform_set_drvdata(pdev, mci); 714 pdata->name = "mv64x60_mc_err"; 715 pdata->irq = NO_IRQ; 716 mci->dev_name = dev_name(&pdev->dev); 717 pdata->edac_idx = edac_mc_idx++; 718 719 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 720 if (!r) { 721 printk(KERN_ERR "%s: Unable to get resource for " 722 "MC err regs\n", __func__); 723 res = -ENOENT; 724 goto err; 725 } 726 727 if (!devm_request_mem_region(&pdev->dev, 728 r->start, 729 resource_size(r), 730 pdata->name)) { 731 printk(KERN_ERR "%s: Error while requesting mem region\n", 732 __func__); 733 res = -EBUSY; 734 goto err; 735 } 736 737 pdata->mc_vbase = devm_ioremap(&pdev->dev, 738 r->start, 739 resource_size(r)); 740 if (!pdata->mc_vbase) { 741 printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__); 742 res = -ENOMEM; 743 goto err; 744 } 745 746 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); 747 if (!(ctl & MV64X60_SDRAM_ECC)) { 748 /* Non-ECC RAM? */ 749 printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__); 750 res = -ENODEV; 751 goto err2; 752 } 753 754 debugf3("%s(): init mci\n", __func__); 755 mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; 756 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; 757 mci->edac_cap = EDAC_FLAG_SECDED; 758 mci->mod_name = EDAC_MOD_STR; 759 mci->mod_ver = MV64x60_REVISION; 760 mci->ctl_name = mv64x60_ctl_name; 761 762 if (edac_op_state == EDAC_OPSTATE_POLL) 763 mci->edac_check = mv64x60_mc_check; 764 765 mci->ctl_page_to_phys = NULL; 766 767 mci->scrub_mode = SCRUB_SW_SRC; 768 769 mv64x60_init_csrows(mci, pdata); 770 771 /* setup MC registers */ 772 out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); 773 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL); 774 ctl = (ctl & 0xff00ffff) | 0x10000; 775 out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); 776 777 if (edac_mc_add_mc(mci)) { 778 debugf3("%s(): failed edac_mc_add_mc()\n", __func__); 779 goto err; 780 } 781 782 if (edac_op_state == EDAC_OPSTATE_INT) { 783 /* acquire interrupt that reports errors */ 784 pdata->irq = platform_get_irq(pdev, 0); 785 res = devm_request_irq(&pdev->dev, 786 pdata->irq, 787 mv64x60_mc_isr, 788 IRQF_DISABLED, 789 "[EDAC] MC err", 790 mci); 791 if (res < 0) { 792 printk(KERN_ERR "%s: Unable to request irq %d for " 793 "MV64x60 DRAM ERR\n", __func__, pdata->irq); 794 res = -ENODEV; 795 goto err2; 796 } 797 798 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n", 799 pdata->irq); 800 } 801 802 /* get this far and it's successful */ 803 debugf3("%s(): success\n", __func__); 804 805 return 0; 806 807err2: 808 edac_mc_del_mc(&pdev->dev); 809err: 810 devres_release_group(&pdev->dev, mv64x60_mc_err_probe); 811 edac_mc_free(mci); 812 return res; 813} 814 815static int mv64x60_mc_err_remove(struct platform_device *pdev) 816{ 817 struct mem_ctl_info *mci = platform_get_drvdata(pdev); 818 819 debugf0("%s()\n", __func__); 820 821 edac_mc_del_mc(&pdev->dev); 822 edac_mc_free(mci); 823 return 0; 824} 825 826static struct platform_driver mv64x60_mc_err_driver = { 827 .probe = mv64x60_mc_err_probe, 828 .remove = mv64x60_mc_err_remove, 829 .driver = { 830 .name = "mv64x60_mc_err", 831 } 832}; 833 834static int __init mv64x60_edac_init(void) 835{ 836 int ret = 0; 837 838 printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n"); 839 printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n"); 840 /* make sure error reporting method is sane */ 841 switch (edac_op_state) { 842 case EDAC_OPSTATE_POLL: 843 case EDAC_OPSTATE_INT: 844 break; 845 default: 846 edac_op_state = EDAC_OPSTATE_INT; 847 break; 848 } 849 850 ret = platform_driver_register(&mv64x60_mc_err_driver); 851 if (ret) 852 printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n"); 853 854 ret = platform_driver_register(&mv64x60_cpu_err_driver); 855 if (ret) 856 printk(KERN_WARNING EDAC_MOD_STR 857 "CPU err failed to register\n"); 858 859 ret = platform_driver_register(&mv64x60_sram_err_driver); 860 if (ret) 861 printk(KERN_WARNING EDAC_MOD_STR 862 "SRAM err failed to register\n"); 863 864#ifdef CONFIG_PCI 865 ret = platform_driver_register(&mv64x60_pci_err_driver); 866 if (ret) 867 printk(KERN_WARNING EDAC_MOD_STR 868 "PCI err failed to register\n"); 869#endif 870 871 return ret; 872} 873module_init(mv64x60_edac_init); 874 875static void __exit mv64x60_edac_exit(void) 876{ 877#ifdef CONFIG_PCI 878 platform_driver_unregister(&mv64x60_pci_err_driver); 879#endif 880 platform_driver_unregister(&mv64x60_sram_err_driver); 881 platform_driver_unregister(&mv64x60_cpu_err_driver); 882 platform_driver_unregister(&mv64x60_mc_err_driver); 883} 884module_exit(mv64x60_edac_exit); 885 886MODULE_LICENSE("GPL"); 887MODULE_AUTHOR("Montavista Software, Inc."); 888module_param(edac_op_state, int, 0444); 889MODULE_PARM_DESC(edac_op_state, 890 "EDAC Error Reporting state: 0=Poll, 2=Interrupt"); 891