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_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