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.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 | |
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, compat: "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(node: np, index: 0); |
35 | of_node_put(node: 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(val: 0x01, addr: mapped_l2_edac_addr); |
43 | iounmap(addr: mapped_l2_edac_addr); |
44 | } |
45 | |
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, compat: "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(node: np, index: 0); |
59 | of_node_put(node: 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, addr: (sys_manager_base_addr + |
71 | A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST)); |
72 | /* Enable ECC */ |
73 | writel(A10_SYSMGR_ECC_INTMASK_CLR_L2, addr: sys_manager_base_addr + |
74 | A10_SYSMGR_ECC_INTMASK_CLR_OFST); |
75 | writel(A10_MPU_CTRL_L2_ECC_EN, addr: mapped_l2_edac_addr + |
76 | A10_MPU_CTRL_L2_ECC_OFST); |
77 | exit: |
78 | iounmap(addr: mapped_l2_edac_addr); |
79 | } |
80 | |