linux/drivers/edac/mv64x60_edac.c
<<
>>
Prefs
   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