root/drivers/edac/mv64x60_edac.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mv64x60_pci_check
  2. mv64x60_pci_isr
  3. mv64x60_pci_fixup
  4. mv64x60_pci_err_probe
  5. mv64x60_pci_err_remove
  6. mv64x60_sram_check
  7. mv64x60_sram_isr
  8. mv64x60_sram_err_probe
  9. mv64x60_sram_err_remove
  10. mv64x60_cpu_check
  11. mv64x60_cpu_isr
  12. mv64x60_cpu_err_probe
  13. mv64x60_cpu_err_remove
  14. mv64x60_mc_check
  15. mv64x60_mc_isr
  16. get_total_mem
  17. mv64x60_init_csrows
  18. mv64x60_mc_err_probe
  19. mv64x60_mc_err_remove
  20. mv64x60_edac_init
  21. mv64x60_edac_exit

   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 
  23 static const char *mv64x60_ctl_name = "MV64x60";
  24 static int edac_dev_idx;
  25 static int edac_pci_idx;
  26 static int edac_mc_idx;
  27 
  28 /*********************** PCI err device **********************************/
  29 #ifdef CONFIG_PCI
  30 static 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 
  58 static 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. */
  80 static 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 
 102 static 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 
 199 err2:
 200         edac_pci_del_device(&pdev->dev);
 201 err:
 202         edac_pci_free_ctl_info(pci);
 203         devres_release_group(&pdev->dev, mv64x60_pci_err_probe);
 204         return res;
 205 }
 206 
 207 static 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 
 220 static 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 **********************************/
 231 static 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 
 257 static 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 
 272 static 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 
 367 err2:
 368         edac_device_del_device(&pdev->dev);
 369 err:
 370         devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
 371         edac_device_free_ctl_info(edac_dev);
 372         return res;
 373 }
 374 
 375 static 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 
 387 static 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 **********************************/
 396 static 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 
 423 static 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 
 439 static 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 
 561 err2:
 562         edac_device_del_device(&pdev->dev);
 563 err:
 564         devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
 565         edac_device_free_ctl_info(edac_dev);
 566         return res;
 567 }
 568 
 569 static 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 
 580 static 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 
 590 static 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 
 626 static 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 
 642 static 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 
 656 static 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 
 696 static 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 
 817 err2:
 818         edac_mc_del_mc(&pdev->dev);
 819 err:
 820         devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
 821         edac_mc_free(mci);
 822         return res;
 823 }
 824 
 825 static 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 
 836 static 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 
 844 static 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 
 853 static 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 }
 871 module_init(mv64x60_edac_init);
 872 
 873 static void __exit mv64x60_edac_exit(void)
 874 {
 875         platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 876 }
 877 module_exit(mv64x60_edac_exit);
 878 
 879 MODULE_LICENSE("GPL");
 880 MODULE_AUTHOR("Montavista Software, Inc.");
 881 module_param(edac_op_state, int, 0444);
 882 MODULE_PARM_DESC(edac_op_state,
 883                  "EDAC Error Reporting state: 0=Poll, 2=Interrupt");

/* [<][>][^][v][top][bottom][index][help] */