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