@@ -550,6 +550,7 @@ module_platform_driver(altr_edac_driver);
550550
551551const struct edac_device_prv_data ocramecc_data ;
552552const struct edac_device_prv_data l2ecc_data ;
553+ const struct edac_device_prv_data a10_ocramecc_data ;
553554const struct edac_device_prv_data a10_l2ecc_data ;
554555
555556static irqreturn_t altr_edac_device_handler (int irq , void * dev_id )
@@ -674,6 +675,16 @@ static const struct file_operations altr_edac_device_inject_fops = {
674675 .llseek = generic_file_llseek ,
675676};
676677
678+ static ssize_t altr_edac_a10_device_trig (struct file * file ,
679+ const char __user * user_buf ,
680+ size_t count , loff_t * ppos );
681+
682+ static const struct file_operations altr_edac_a10_device_inject_fops = {
683+ .open = simple_open ,
684+ .write = altr_edac_a10_device_trig ,
685+ .llseek = generic_file_llseek ,
686+ };
687+
677688static void altr_create_edacdev_dbgfs (struct edac_device_ctl_info * edac_dci ,
678689 const struct edac_device_prv_data * priv )
679690{
@@ -701,6 +712,8 @@ static const struct of_device_id altr_edac_device_of_match[] = {
701712#ifdef CONFIG_EDAC_ALTERA_OCRAM
702713 { .compatible = "altr,socfpga-ocram-ecc" ,
703714 .data = (void * )& ocramecc_data },
715+ { .compatible = "altr,socfpga-a10-ocram-ecc" ,
716+ .data = (void * )& a10_ocramecc_data },
704717#endif
705718 {},
706719};
@@ -889,6 +902,24 @@ const struct edac_device_prv_data ocramecc_data = {
889902 .inject_fops = & altr_edac_device_inject_fops ,
890903};
891904
905+ static irqreturn_t altr_edac_a10_ecc_irq (struct altr_edac_device_dev * dci ,
906+ bool sberr );
907+
908+ const struct edac_device_prv_data a10_ocramecc_data = {
909+ .setup = altr_check_ecc_deps ,
910+ .ce_clear_mask = ALTR_A10_ECC_SERRPENA ,
911+ .ue_clear_mask = ALTR_A10_ECC_DERRPENA ,
912+ .irq_status_mask = A10_SYSMGR_ECC_INTSTAT_OCRAM ,
913+ .dbgfs_name = "altr_ocram_trigger" ,
914+ .ecc_enable_mask = ALTR_A10_OCRAM_ECC_EN_CTL ,
915+ .ecc_en_ofst = ALTR_A10_ECC_CTRL_OFST ,
916+ .ce_set_mask = ALTR_A10_ECC_TSERRA ,
917+ .ue_set_mask = ALTR_A10_ECC_TDERRA ,
918+ .set_err_ofst = ALTR_A10_ECC_INTTEST_OFST ,
919+ .ecc_irq_handler = altr_edac_a10_ecc_irq ,
920+ .inject_fops = & altr_edac_a10_device_inject_fops ,
921+ };
922+
892923#endif /* CONFIG_EDAC_ALTERA_OCRAM */
893924
894925/********************* L2 Cache EDAC Device Functions ********************/
@@ -1007,6 +1038,50 @@ const struct edac_device_prv_data a10_l2ecc_data = {
10071038 * Based on xgene_edac.c peripheral code.
10081039 */
10091040
1041+ static ssize_t altr_edac_a10_device_trig (struct file * file ,
1042+ const char __user * user_buf ,
1043+ size_t count , loff_t * ppos )
1044+ {
1045+ struct edac_device_ctl_info * edac_dci = file -> private_data ;
1046+ struct altr_edac_device_dev * drvdata = edac_dci -> pvt_info ;
1047+ const struct edac_device_prv_data * priv = drvdata -> data ;
1048+ void __iomem * set_addr = (drvdata -> base + priv -> set_err_ofst );
1049+ unsigned long flags ;
1050+ u8 trig_type ;
1051+
1052+ if (!user_buf || get_user (trig_type , user_buf ))
1053+ return - EFAULT ;
1054+
1055+ local_irq_save (flags );
1056+ if (trig_type == ALTR_UE_TRIGGER_CHAR )
1057+ writel (priv -> ue_set_mask , set_addr );
1058+ else
1059+ writel (priv -> ce_set_mask , set_addr );
1060+ /* Ensure the interrupt test bits are set */
1061+ wmb ();
1062+ local_irq_restore (flags );
1063+
1064+ return count ;
1065+ }
1066+
1067+ static irqreturn_t altr_edac_a10_ecc_irq (struct altr_edac_device_dev * dci ,
1068+ bool sberr )
1069+ {
1070+ void __iomem * base = dci -> base ;
1071+
1072+ if (sberr ) {
1073+ writel (ALTR_A10_ECC_SERRPENA ,
1074+ base + ALTR_A10_ECC_INTSTAT_OFST );
1075+ edac_device_handle_ce (dci -> edac_dev , 0 , 0 , dci -> edac_dev_name );
1076+ } else {
1077+ writel (ALTR_A10_ECC_DERRPENA ,
1078+ base + ALTR_A10_ECC_INTSTAT_OFST );
1079+ edac_device_handle_ue (dci -> edac_dev , 0 , 0 , dci -> edac_dev_name );
1080+ panic ("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n" );
1081+ }
1082+ return IRQ_HANDLED ;
1083+ }
1084+
10101085static irqreturn_t altr_edac_a10_irq_handler (int irq , void * dev_id )
10111086{
10121087 irqreturn_t rc = IRQ_NONE ;
@@ -1171,6 +1246,9 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
11711246 continue ;
11721247 if (of_device_is_compatible (child , "altr,socfpga-a10-l2-ecc" ))
11731248 altr_edac_a10_device_add (edac , child );
1249+ else if (of_device_is_compatible (child ,
1250+ "altr,socfpga-a10-ocram-ecc" ))
1251+ altr_edac_a10_device_add (edac , child );
11741252 }
11751253
11761254 return 0 ;
0 commit comments