Skip to content

Commit c7b4be8

Browse files
Thor Thayersuryasaimadhu
authored andcommitted
EDAC, altera: Add Arria10 OCRAM ECC support
Add Arria10 On-Chip RAM ECC handling. Signed-off-by: Thor Thayer <tthayer@opensource.altera.com> Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac <linux-edac@vger.kernel.org> Link: http://lkml.kernel.org/r/1459992174-8015-1-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov <bp@suse.de>
1 parent abd56b3 commit c7b4be8

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

drivers/edac/altera_edac.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ module_platform_driver(altr_edac_driver);
550550

551551
const struct edac_device_prv_data ocramecc_data;
552552
const struct edac_device_prv_data l2ecc_data;
553+
const struct edac_device_prv_data a10_ocramecc_data;
553554
const struct edac_device_prv_data a10_l2ecc_data;
554555

555556
static 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+
677688
static 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+
10101085
static 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;

drivers/edac/altera_edac.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,41 @@ struct altr_sdram_mc_data {
220220
#define ALTR_L2_ECC_INJD BIT(2)
221221

222222
/* Arria10 General ECC Block Module Defines */
223+
#define ALTR_A10_ECC_CTRL_OFST 0x08
224+
#define ALTR_A10_ECC_EN BIT(0)
225+
#define ALTR_A10_ECC_INITA BIT(16)
226+
#define ALTR_A10_ECC_INITB BIT(24)
227+
228+
#define ALTR_A10_ECC_INITSTAT_OFST 0x0C
229+
#define ALTR_A10_ECC_INITCOMPLETEA BIT(0)
230+
#define ALTR_A10_ECC_INITCOMPLETEB BIT(8)
231+
232+
#define ALTR_A10_ECC_ERRINTEN_OFST 0x10
233+
#define ALTR_A10_ECC_SERRINTEN BIT(0)
234+
235+
#define ALTR_A10_ECC_INTSTAT_OFST 0x20
236+
#define ALTR_A10_ECC_SERRPENA BIT(0)
237+
#define ALTR_A10_ECC_DERRPENA BIT(8)
238+
#define ALTR_A10_ECC_ERRPENA_MASK (ALTR_A10_ECC_SERRPENA | \
239+
ALTR_A10_ECC_DERRPENA)
240+
#define ALTR_A10_ECC_SERRPENB BIT(16)
241+
#define ALTR_A10_ECC_DERRPENB BIT(24)
242+
#define ALTR_A10_ECC_ERRPENB_MASK (ALTR_A10_ECC_SERRPENB | \
243+
ALTR_A10_ECC_DERRPENB)
244+
245+
#define ALTR_A10_ECC_INTTEST_OFST 0x24
246+
#define ALTR_A10_ECC_TSERRA BIT(0)
247+
#define ALTR_A10_ECC_TDERRA BIT(8)
248+
249+
/* ECC Manager Defines */
250+
#define A10_SYSMGR_ECC_INTMASK_SET_OFST 0x94
251+
#define A10_SYSMGR_ECC_INTMASK_CLR_OFST 0x98
252+
#define A10_SYSMGR_ECC_INTMASK_OCRAM BIT(1)
253+
223254
#define A10_SYSMGR_ECC_INTSTAT_SERR_OFST 0x9C
224255
#define A10_SYSMGR_ECC_INTSTAT_DERR_OFST 0xA0
225256
#define A10_SYSMGR_ECC_INTSTAT_L2 BIT(0)
257+
#define A10_SYSMGR_ECC_INTSTAT_OCRAM BIT(1)
226258

227259
#define A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST 0xA8
228260
#define A10_SYSGMR_MPU_CLEAR_L2_ECC_SB BIT(15)
@@ -245,6 +277,9 @@ struct altr_sdram_mc_data {
245277
#define ALTR_A10_L2_ECC_CE_INJ_MASK 0x00000101
246278
#define ALTR_A10_L2_ECC_UE_INJ_MASK 0x00010101
247279

280+
/* Arria 10 OCRAM ECC Management Group Defines */
281+
#define ALTR_A10_OCRAM_ECC_EN_CTL (BIT(1) | BIT(0))
282+
248283
struct altr_edac_device_dev;
249284

250285
struct edac_device_prv_data {

0 commit comments

Comments
 (0)