altera_edac.c (d1208404dd477c142680437137c9996b95bfd508) | altera_edac.c (c3eea1942a16db52ebea0382bd5826f75b9b7e9b) |
---|---|
1/* | 1/* |
2 * Copyright Altera Corporation (C) 2014-2015. All rights reserved. | 2 * Copyright Altera Corporation (C) 2014-2016. All rights reserved. |
3 * Copyright 2011-2012 Calxeda, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * Adapted from the highbank_mc_edac driver. 18 */ 19 | 3 * Copyright 2011-2012 Calxeda, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * Adapted from the highbank_mc_edac driver. 18 */ 19 |
20#include <asm/cacheflush.h> |
|
20#include <linux/ctype.h> 21#include <linux/edac.h> | 21#include <linux/ctype.h> 22#include <linux/edac.h> |
23#include <linux/genalloc.h> |
|
22#include <linux/interrupt.h> 23#include <linux/kernel.h> 24#include <linux/mfd/syscon.h> 25#include <linux/of_platform.h> 26#include <linux/platform_device.h> 27#include <linux/regmap.h> 28#include <linux/types.h> 29#include <linux/uaccess.h> 30 31#include "altera_edac.h" 32#include "edac_core.h" 33#include "edac_module.h" 34 35#define EDAC_MOD_STR "altera_edac" 36#define EDAC_VERSION "1" | 24#include <linux/interrupt.h> 25#include <linux/kernel.h> 26#include <linux/mfd/syscon.h> 27#include <linux/of_platform.h> 28#include <linux/platform_device.h> 29#include <linux/regmap.h> 30#include <linux/types.h> 31#include <linux/uaccess.h> 32 33#include "altera_edac.h" 34#include "edac_core.h" 35#include "edac_module.h" 36 37#define EDAC_MOD_STR "altera_edac" 38#define EDAC_VERSION "1" |
39#define EDAC_DEVICE "Altera" |
|
37 38static const struct altr_sdram_prv_data c5_data = { 39 .ecc_ctrl_offset = CV_CTLCFG_OFST, 40 .ecc_ctl_en_mask = CV_CTLCFG_ECC_AUTO_EN, 41 .ecc_stat_offset = CV_DRAMSTS_OFST, 42 .ecc_stat_ce_mask = CV_DRAMSTS_SBEERR, 43 .ecc_stat_ue_mask = CV_DRAMSTS_DBEERR, 44 .ecc_saddr_offset = CV_ERRADDR_OFST, --- 25 unchanged lines hidden (view full) --- 70 .ecc_irq_clr_mask = (A10_INTSTAT_SBEERR | A10_INTSTAT_DBEERR), 71 .ecc_cnt_rst_offset = A10_ECCCTRL1_OFST, 72 .ecc_cnt_rst_mask = A10_ECC_CNT_RESET_MASK, 73 .ce_ue_trgr_offset = A10_DIAGINTTEST_OFST, 74 .ce_set_mask = A10_DIAGINT_TSERRA_MASK, 75 .ue_set_mask = A10_DIAGINT_TDERRA_MASK, 76}; 77 | 40 41static const struct altr_sdram_prv_data c5_data = { 42 .ecc_ctrl_offset = CV_CTLCFG_OFST, 43 .ecc_ctl_en_mask = CV_CTLCFG_ECC_AUTO_EN, 44 .ecc_stat_offset = CV_DRAMSTS_OFST, 45 .ecc_stat_ce_mask = CV_DRAMSTS_SBEERR, 46 .ecc_stat_ue_mask = CV_DRAMSTS_DBEERR, 47 .ecc_saddr_offset = CV_ERRADDR_OFST, --- 25 unchanged lines hidden (view full) --- 73 .ecc_irq_clr_mask = (A10_INTSTAT_SBEERR | A10_INTSTAT_DBEERR), 74 .ecc_cnt_rst_offset = A10_ECCCTRL1_OFST, 75 .ecc_cnt_rst_mask = A10_ECC_CNT_RESET_MASK, 76 .ce_ue_trgr_offset = A10_DIAGINTTEST_OFST, 77 .ce_set_mask = A10_DIAGINT_TSERRA_MASK, 78 .ue_set_mask = A10_DIAGINT_TDERRA_MASK, 79}; 80 |
81/************************** EDAC Device Defines **************************/ 82 83/* OCRAM ECC Management Group Defines */ 84#define ALTR_MAN_GRP_OCRAM_ECC_OFFSET 0x04 85#define ALTR_OCR_ECC_EN BIT(0) 86#define ALTR_OCR_ECC_INJS BIT(1) 87#define ALTR_OCR_ECC_INJD BIT(2) 88#define ALTR_OCR_ECC_SERR BIT(3) 89#define ALTR_OCR_ECC_DERR BIT(4) 90 91/* L2 ECC Management Group Defines */ 92#define ALTR_MAN_GRP_L2_ECC_OFFSET 0x00 93#define ALTR_L2_ECC_EN BIT(0) 94#define ALTR_L2_ECC_INJS BIT(1) 95#define ALTR_L2_ECC_INJD BIT(2) 96 97#define ALTR_UE_TRIGGER_CHAR 'U' /* Trigger for UE */ 98#define ALTR_TRIGGER_READ_WRD_CNT 32 /* Line size x 4 */ 99#define ALTR_TRIG_OCRAM_BYTE_SIZE 128 /* Line size x 4 */ 100#define ALTR_TRIG_L2C_BYTE_SIZE 4096 /* Full Page */ 101 102/*********************** EDAC Memory Controller Functions ****************/ 103 104/* The SDRAM controller uses the EDAC Memory Controller framework. */ 105 |
|
78static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id) 79{ 80 struct mem_ctl_info *mci = dev_id; 81 struct altr_sdram_mc_data *drvdata = mci->pvt_info; 82 const struct altr_sdram_prv_data *priv = drvdata->data; 83 u32 status, err_count = 1, err_addr; 84 85 regmap_read(drvdata->mc_vbase, priv->ecc_stat_offset, &status); --- 413 unchanged lines hidden (view full) --- 499 .pm = &altr_sdram_pm_ops, 500#endif 501 .of_match_table = altr_sdram_ctrl_of_match, 502 }, 503}; 504 505module_platform_driver(altr_sdram_edac_driver); 506 | 106static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id) 107{ 108 struct mem_ctl_info *mci = dev_id; 109 struct altr_sdram_mc_data *drvdata = mci->pvt_info; 110 const struct altr_sdram_prv_data *priv = drvdata->data; 111 u32 status, err_count = 1, err_addr; 112 113 regmap_read(drvdata->mc_vbase, priv->ecc_stat_offset, &status); --- 413 unchanged lines hidden (view full) --- 527 .pm = &altr_sdram_pm_ops, 528#endif 529 .of_match_table = altr_sdram_ctrl_of_match, 530 }, 531}; 532 533module_platform_driver(altr_sdram_edac_driver); 534 |
535/************************* EDAC Parent Probe *************************/ 536 537static const struct of_device_id altr_edac_device_of_match[]; 538 539static const struct of_device_id altr_edac_of_match[] = { 540 { .compatible = "altr,socfpga-ecc-manager" }, 541 {}, 542}; 543MODULE_DEVICE_TABLE(of, altr_edac_of_match); 544 545static int altr_edac_probe(struct platform_device *pdev) 546{ 547 of_platform_populate(pdev->dev.of_node, altr_edac_device_of_match, 548 NULL, &pdev->dev); 549 return 0; 550} 551 552static struct platform_driver altr_edac_driver = { 553 .probe = altr_edac_probe, 554 .driver = { 555 .name = "socfpga_ecc_manager", 556 .of_match_table = altr_edac_of_match, 557 }, 558}; 559module_platform_driver(altr_edac_driver); 560 561/************************* EDAC Device Functions *************************/ 562 563/* 564 * EDAC Device Functions (shared between various IPs). 565 * The discrete memories use the EDAC Device framework. The probe 566 * and error handling functions are very similar between memories 567 * so they are shared. The memory allocation and freeing for EDAC 568 * trigger testing are different for each memory. 569 */ 570 571const struct edac_device_prv_data ocramecc_data; 572const struct edac_device_prv_data l2ecc_data; 573 574struct edac_device_prv_data { 575 int (*setup)(struct platform_device *pdev, void __iomem *base); 576 int ce_clear_mask; 577 int ue_clear_mask; 578 char dbgfs_name[20]; 579 void * (*alloc_mem)(size_t size, void **other); 580 void (*free_mem)(void *p, size_t size, void *other); 581 int ecc_enable_mask; 582 int ce_set_mask; 583 int ue_set_mask; 584 int trig_alloc_sz; 585}; 586 587struct altr_edac_device_dev { 588 void __iomem *base; 589 int sb_irq; 590 int db_irq; 591 const struct edac_device_prv_data *data; 592 struct dentry *debugfs_dir; 593 char *edac_dev_name; 594}; 595 596static irqreturn_t altr_edac_device_handler(int irq, void *dev_id) 597{ 598 irqreturn_t ret_value = IRQ_NONE; 599 struct edac_device_ctl_info *dci = dev_id; 600 struct altr_edac_device_dev *drvdata = dci->pvt_info; 601 const struct edac_device_prv_data *priv = drvdata->data; 602 603 if (irq == drvdata->sb_irq) { 604 if (priv->ce_clear_mask) 605 writel(priv->ce_clear_mask, drvdata->base); 606 edac_device_handle_ce(dci, 0, 0, drvdata->edac_dev_name); 607 ret_value = IRQ_HANDLED; 608 } else if (irq == drvdata->db_irq) { 609 if (priv->ue_clear_mask) 610 writel(priv->ue_clear_mask, drvdata->base); 611 edac_device_handle_ue(dci, 0, 0, drvdata->edac_dev_name); 612 panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n"); 613 ret_value = IRQ_HANDLED; 614 } else { 615 WARN_ON(1); 616 } 617 618 return ret_value; 619} 620 621static ssize_t altr_edac_device_trig(struct file *file, 622 const char __user *user_buf, 623 size_t count, loff_t *ppos) 624 625{ 626 u32 *ptemp, i, error_mask; 627 int result = 0; 628 u8 trig_type; 629 unsigned long flags; 630 struct edac_device_ctl_info *edac_dci = file->private_data; 631 struct altr_edac_device_dev *drvdata = edac_dci->pvt_info; 632 const struct edac_device_prv_data *priv = drvdata->data; 633 void *generic_ptr = edac_dci->dev; 634 635 if (!user_buf || get_user(trig_type, user_buf)) 636 return -EFAULT; 637 638 if (!priv->alloc_mem) 639 return -ENOMEM; 640 641 /* 642 * Note that generic_ptr is initialized to the device * but in 643 * some alloc_functions, this is overridden and returns data. 644 */ 645 ptemp = priv->alloc_mem(priv->trig_alloc_sz, &generic_ptr); 646 if (!ptemp) { 647 edac_printk(KERN_ERR, EDAC_DEVICE, 648 "Inject: Buffer Allocation error\n"); 649 return -ENOMEM; 650 } 651 652 if (trig_type == ALTR_UE_TRIGGER_CHAR) 653 error_mask = priv->ue_set_mask; 654 else 655 error_mask = priv->ce_set_mask; 656 657 edac_printk(KERN_ALERT, EDAC_DEVICE, 658 "Trigger Error Mask (0x%X)\n", error_mask); 659 660 local_irq_save(flags); 661 /* write ECC corrupted data out. */ 662 for (i = 0; i < (priv->trig_alloc_sz / sizeof(*ptemp)); i++) { 663 /* Read data so we're in the correct state */ 664 rmb(); 665 if (ACCESS_ONCE(ptemp[i])) 666 result = -1; 667 /* Toggle Error bit (it is latched), leave ECC enabled */ 668 writel(error_mask, drvdata->base); 669 writel(priv->ecc_enable_mask, drvdata->base); 670 ptemp[i] = i; 671 } 672 /* Ensure it has been written out */ 673 wmb(); 674 local_irq_restore(flags); 675 676 if (result) 677 edac_printk(KERN_ERR, EDAC_DEVICE, "Mem Not Cleared\n"); 678 679 /* Read out written data. ECC error caused here */ 680 for (i = 0; i < ALTR_TRIGGER_READ_WRD_CNT; i++) 681 if (ACCESS_ONCE(ptemp[i]) != i) 682 edac_printk(KERN_ERR, EDAC_DEVICE, 683 "Read doesn't match written data\n"); 684 685 if (priv->free_mem) 686 priv->free_mem(ptemp, priv->trig_alloc_sz, generic_ptr); 687 688 return count; 689} 690 691static const struct file_operations altr_edac_device_inject_fops = { 692 .open = simple_open, 693 .write = altr_edac_device_trig, 694 .llseek = generic_file_llseek, 695}; 696 697static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci, 698 const struct edac_device_prv_data *priv) 699{ 700 struct altr_edac_device_dev *drvdata = edac_dci->pvt_info; 701 702 if (!IS_ENABLED(CONFIG_EDAC_DEBUG)) 703 return; 704 705 drvdata->debugfs_dir = edac_debugfs_create_dir(drvdata->edac_dev_name); 706 if (!drvdata->debugfs_dir) 707 return; 708 709 if (!edac_debugfs_create_file(priv->dbgfs_name, S_IWUSR, 710 drvdata->debugfs_dir, edac_dci, 711 &altr_edac_device_inject_fops)) 712 debugfs_remove_recursive(drvdata->debugfs_dir); 713} 714 715static const struct of_device_id altr_edac_device_of_match[] = { 716#ifdef CONFIG_EDAC_ALTERA_L2C 717 { .compatible = "altr,socfpga-l2-ecc", .data = (void *)&l2ecc_data }, 718#endif 719#ifdef CONFIG_EDAC_ALTERA_OCRAM 720 { .compatible = "altr,socfpga-ocram-ecc", 721 .data = (void *)&ocramecc_data }, 722#endif 723 {}, 724}; 725MODULE_DEVICE_TABLE(of, altr_edac_device_of_match); 726 727/* 728 * altr_edac_device_probe() 729 * This is a generic EDAC device driver that will support 730 * various Altera memory devices such as the L2 cache ECC and 731 * OCRAM ECC as well as the memories for other peripherals. 732 * Module specific initialization is done by passing the 733 * function index in the device tree. 734 */ 735static int altr_edac_device_probe(struct platform_device *pdev) 736{ 737 struct edac_device_ctl_info *dci; 738 struct altr_edac_device_dev *drvdata; 739 struct resource *r; 740 int res = 0; 741 struct device_node *np = pdev->dev.of_node; 742 char *ecc_name = (char *)np->name; 743 static int dev_instance; 744 745 if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { 746 edac_printk(KERN_ERR, EDAC_DEVICE, 747 "Unable to open devm\n"); 748 return -ENOMEM; 749 } 750 751 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 752 if (!r) { 753 edac_printk(KERN_ERR, EDAC_DEVICE, 754 "Unable to get mem resource\n"); 755 res = -ENODEV; 756 goto fail; 757 } 758 759 if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r), 760 dev_name(&pdev->dev))) { 761 edac_printk(KERN_ERR, EDAC_DEVICE, 762 "%s:Error requesting mem region\n", ecc_name); 763 res = -EBUSY; 764 goto fail; 765 } 766 767 dci = edac_device_alloc_ctl_info(sizeof(*drvdata), ecc_name, 768 1, ecc_name, 1, 0, NULL, 0, 769 dev_instance++); 770 771 if (!dci) { 772 edac_printk(KERN_ERR, EDAC_DEVICE, 773 "%s: Unable to allocate EDAC device\n", ecc_name); 774 res = -ENOMEM; 775 goto fail; 776 } 777 778 drvdata = dci->pvt_info; 779 dci->dev = &pdev->dev; 780 platform_set_drvdata(pdev, dci); 781 drvdata->edac_dev_name = ecc_name; 782 783 drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); 784 if (!drvdata->base) 785 goto fail1; 786 787 /* Get driver specific data for this EDAC device */ 788 drvdata->data = of_match_node(altr_edac_device_of_match, np)->data; 789 790 /* Check specific dependencies for the module */ 791 if (drvdata->data->setup) { 792 res = drvdata->data->setup(pdev, drvdata->base); 793 if (res) 794 goto fail1; 795 } 796 797 drvdata->sb_irq = platform_get_irq(pdev, 0); 798 res = devm_request_irq(&pdev->dev, drvdata->sb_irq, 799 altr_edac_device_handler, 800 0, dev_name(&pdev->dev), dci); 801 if (res) 802 goto fail1; 803 804 drvdata->db_irq = platform_get_irq(pdev, 1); 805 res = devm_request_irq(&pdev->dev, drvdata->db_irq, 806 altr_edac_device_handler, 807 0, dev_name(&pdev->dev), dci); 808 if (res) 809 goto fail1; 810 811 dci->mod_name = "Altera ECC Manager"; 812 dci->dev_name = drvdata->edac_dev_name; 813 814 res = edac_device_add_device(dci); 815 if (res) 816 goto fail1; 817 818 altr_create_edacdev_dbgfs(dci, drvdata->data); 819 820 devres_close_group(&pdev->dev, NULL); 821 822 return 0; 823 824fail1: 825 edac_device_free_ctl_info(dci); 826fail: 827 devres_release_group(&pdev->dev, NULL); 828 edac_printk(KERN_ERR, EDAC_DEVICE, 829 "%s:Error setting up EDAC device: %d\n", ecc_name, res); 830 831 return res; 832} 833 834static int altr_edac_device_remove(struct platform_device *pdev) 835{ 836 struct edac_device_ctl_info *dci = platform_get_drvdata(pdev); 837 struct altr_edac_device_dev *drvdata = dci->pvt_info; 838 839 debugfs_remove_recursive(drvdata->debugfs_dir); 840 edac_device_del_device(&pdev->dev); 841 edac_device_free_ctl_info(dci); 842 843 return 0; 844} 845 846static struct platform_driver altr_edac_device_driver = { 847 .probe = altr_edac_device_probe, 848 .remove = altr_edac_device_remove, 849 .driver = { 850 .name = "altr_edac_device", 851 .of_match_table = altr_edac_device_of_match, 852 }, 853}; 854module_platform_driver(altr_edac_device_driver); 855 856/*********************** OCRAM EDAC Device Functions *********************/ 857 858#ifdef CONFIG_EDAC_ALTERA_OCRAM 859 860static void *ocram_alloc_mem(size_t size, void **other) 861{ 862 struct device_node *np; 863 struct gen_pool *gp; 864 void *sram_addr; 865 866 np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc"); 867 if (!np) 868 return NULL; 869 870 gp = of_gen_pool_get(np, "iram", 0); 871 of_node_put(np); 872 if (!gp) 873 return NULL; 874 875 sram_addr = (void *)gen_pool_alloc(gp, size); 876 if (!sram_addr) 877 return NULL; 878 879 memset(sram_addr, 0, size); 880 /* Ensure data is written out */ 881 wmb(); 882 883 /* Remember this handle for freeing later */ 884 *other = gp; 885 886 return sram_addr; 887} 888 889static void ocram_free_mem(void *p, size_t size, void *other) 890{ 891 gen_pool_free((struct gen_pool *)other, (u32)p, size); 892} 893 894/* 895 * altr_ocram_check_deps() 896 * Test for OCRAM cache ECC dependencies upon entry because 897 * platform specific startup should have initialized the 898 * On-Chip RAM memory and enabled the ECC. 899 * Can't turn on ECC here because accessing un-initialized 900 * memory will cause CE/UE errors possibly causing an ABORT. 901 */ 902static int altr_ocram_check_deps(struct platform_device *pdev, 903 void __iomem *base) 904{ 905 if (readl(base) & ALTR_OCR_ECC_EN) 906 return 0; 907 908 edac_printk(KERN_ERR, EDAC_DEVICE, 909 "OCRAM: No ECC present or ECC disabled.\n"); 910 return -ENODEV; 911} 912 913const struct edac_device_prv_data ocramecc_data = { 914 .setup = altr_ocram_check_deps, 915 .ce_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_SERR), 916 .ue_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_DERR), 917 .dbgfs_name = "altr_ocram_trigger", 918 .alloc_mem = ocram_alloc_mem, 919 .free_mem = ocram_free_mem, 920 .ecc_enable_mask = ALTR_OCR_ECC_EN, 921 .ce_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJS), 922 .ue_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJD), 923 .trig_alloc_sz = ALTR_TRIG_OCRAM_BYTE_SIZE, 924}; 925 926#endif /* CONFIG_EDAC_ALTERA_OCRAM */ 927 928/********************* L2 Cache EDAC Device Functions ********************/ 929 930#ifdef CONFIG_EDAC_ALTERA_L2C 931 932static void *l2_alloc_mem(size_t size, void **other) 933{ 934 struct device *dev = *other; 935 void *ptemp = devm_kzalloc(dev, size, GFP_KERNEL); 936 937 if (!ptemp) 938 return NULL; 939 940 /* Make sure everything is written out */ 941 wmb(); 942 943 /* 944 * Clean all cache levels up to LoC (includes L2) 945 * This ensures the corrupted data is written into 946 * L2 cache for readback test (which causes ECC error). 947 */ 948 flush_cache_all(); 949 950 return ptemp; 951} 952 953static void l2_free_mem(void *p, size_t size, void *other) 954{ 955 struct device *dev = other; 956 957 if (dev && p) 958 devm_kfree(dev, p); 959} 960 961/* 962 * altr_l2_check_deps() 963 * Test for L2 cache ECC dependencies upon entry because 964 * platform specific startup should have initialized the L2 965 * memory and enabled the ECC. 966 * Bail if ECC is not enabled. 967 * Note that L2 Cache Enable is forced at build time. 968 */ 969static int altr_l2_check_deps(struct platform_device *pdev, 970 void __iomem *base) 971{ 972 if (readl(base) & ALTR_L2_ECC_EN) 973 return 0; 974 975 edac_printk(KERN_ERR, EDAC_DEVICE, 976 "L2: No ECC present, or ECC disabled\n"); 977 return -ENODEV; 978} 979 980const struct edac_device_prv_data l2ecc_data = { 981 .setup = altr_l2_check_deps, 982 .ce_clear_mask = 0, 983 .ue_clear_mask = 0, 984 .dbgfs_name = "altr_l2_trigger", 985 .alloc_mem = l2_alloc_mem, 986 .free_mem = l2_free_mem, 987 .ecc_enable_mask = ALTR_L2_ECC_EN, 988 .ce_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJS), 989 .ue_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJD), 990 .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE, 991}; 992 993#endif /* CONFIG_EDAC_ALTERA_L2C */ 994 |
|
507MODULE_LICENSE("GPL v2"); 508MODULE_AUTHOR("Thor Thayer"); | 995MODULE_LICENSE("GPL v2"); 996MODULE_AUTHOR("Thor Thayer"); |
509MODULE_DESCRIPTION("EDAC Driver for Altera SDRAM Controller"); | 997MODULE_DESCRIPTION("EDAC Driver for Altera Memories"); |