1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright Altera Corporation (C) 2016. All rights reserved.
4  */
5 #include <linux/io.h>
6 #include <linux/of_platform.h>
7 #include <linux/of_address.h>
8 
9 #include "core.h"
10 
11 /* A10 System Manager L2 ECC Control register */
12 #define A10_MPU_CTRL_L2_ECC_OFST          0x0
13 #define A10_MPU_CTRL_L2_ECC_EN            BIT(0)
14 
15 /* A10 System Manager Global IRQ Mask register */
16 #define A10_SYSMGR_ECC_INTMASK_CLR_OFST   0x98
17 #define A10_SYSMGR_ECC_INTMASK_CLR_L2     BIT(0)
18 
19 /* A10 System Manager L2 ECC IRQ Clear register */
20 #define A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST  0xA8
21 #define A10_SYSMGR_MPU_CLEAR_L2_ECC       (BIT(31) | BIT(15))
22 
socfpga_init_l2_ecc(void)23 void socfpga_init_l2_ecc(void)
24 {
25 	struct device_node *np;
26 	void __iomem *mapped_l2_edac_addr;
27 
28 	np = of_find_compatible_node(NULL, NULL, "altr,socfpga-l2-ecc");
29 	if (!np) {
30 		pr_err("Unable to find socfpga-l2-ecc in dtb\n");
31 		return;
32 	}
33 
34 	mapped_l2_edac_addr = of_iomap(np, 0);
35 	of_node_put(np);
36 	if (!mapped_l2_edac_addr) {
37 		pr_err("Unable to find L2 ECC mapping in dtb\n");
38 		return;
39 	}
40 
41 	/* Enable ECC */
42 	writel(0x01, mapped_l2_edac_addr);
43 	iounmap(mapped_l2_edac_addr);
44 }
45 
socfpga_init_arria10_l2_ecc(void)46 void socfpga_init_arria10_l2_ecc(void)
47 {
48 	struct device_node *np;
49 	void __iomem *mapped_l2_edac_addr;
50 
51 	/* Find the L2 EDAC device tree node */
52 	np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-l2-ecc");
53 	if (!np) {
54 		pr_err("Unable to find socfpga-a10-l2-ecc in dtb\n");
55 		return;
56 	}
57 
58 	mapped_l2_edac_addr = of_iomap(np, 0);
59 	of_node_put(np);
60 	if (!mapped_l2_edac_addr) {
61 		pr_err("Unable to find L2 ECC mapping in dtb\n");
62 		return;
63 	}
64 
65 	if (!sys_manager_base_addr) {
66 		pr_err("System Manager not mapped for L2 ECC\n");
67 		goto exit;
68 	}
69 	/* Clear any pending IRQs */
70 	writel(A10_SYSMGR_MPU_CLEAR_L2_ECC, (sys_manager_base_addr +
71 	       A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST));
72 	/* Enable ECC */
73 	writel(A10_SYSMGR_ECC_INTMASK_CLR_L2, sys_manager_base_addr +
74 	       A10_SYSMGR_ECC_INTMASK_CLR_OFST);
75 	writel(A10_MPU_CTRL_L2_ECC_EN, mapped_l2_edac_addr +
76 	       A10_MPU_CTRL_L2_ECC_OFST);
77 exit:
78 	iounmap(mapped_l2_edac_addr);
79 }
80