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
23void 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
46void 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);
77exit:
78	iounmap(mapped_l2_edac_addr);
79}
80