162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright Altera Corporation (C) 2016. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#include <linux/io.h> 662306a36Sopenharmony_ci#include <linux/of.h> 762306a36Sopenharmony_ci#include <linux/of_address.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "core.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* A10 System Manager L2 ECC Control register */ 1262306a36Sopenharmony_ci#define A10_MPU_CTRL_L2_ECC_OFST 0x0 1362306a36Sopenharmony_ci#define A10_MPU_CTRL_L2_ECC_EN BIT(0) 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* A10 System Manager Global IRQ Mask register */ 1662306a36Sopenharmony_ci#define A10_SYSMGR_ECC_INTMASK_CLR_OFST 0x98 1762306a36Sopenharmony_ci#define A10_SYSMGR_ECC_INTMASK_CLR_L2 BIT(0) 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* A10 System Manager L2 ECC IRQ Clear register */ 2062306a36Sopenharmony_ci#define A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST 0xA8 2162306a36Sopenharmony_ci#define A10_SYSMGR_MPU_CLEAR_L2_ECC (BIT(31) | BIT(15)) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_civoid socfpga_init_l2_ecc(void) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci struct device_node *np; 2662306a36Sopenharmony_ci void __iomem *mapped_l2_edac_addr; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "altr,socfpga-l2-ecc"); 2962306a36Sopenharmony_ci if (!np) { 3062306a36Sopenharmony_ci pr_err("Unable to find socfpga-l2-ecc in dtb\n"); 3162306a36Sopenharmony_ci return; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci mapped_l2_edac_addr = of_iomap(np, 0); 3562306a36Sopenharmony_ci of_node_put(np); 3662306a36Sopenharmony_ci if (!mapped_l2_edac_addr) { 3762306a36Sopenharmony_ci pr_err("Unable to find L2 ECC mapping in dtb\n"); 3862306a36Sopenharmony_ci return; 3962306a36Sopenharmony_ci } 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* Enable ECC */ 4262306a36Sopenharmony_ci writel(0x01, mapped_l2_edac_addr); 4362306a36Sopenharmony_ci iounmap(mapped_l2_edac_addr); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_civoid socfpga_init_arria10_l2_ecc(void) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct device_node *np; 4962306a36Sopenharmony_ci void __iomem *mapped_l2_edac_addr; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* Find the L2 EDAC device tree node */ 5262306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-l2-ecc"); 5362306a36Sopenharmony_ci if (!np) { 5462306a36Sopenharmony_ci pr_err("Unable to find socfpga-a10-l2-ecc in dtb\n"); 5562306a36Sopenharmony_ci return; 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci mapped_l2_edac_addr = of_iomap(np, 0); 5962306a36Sopenharmony_ci of_node_put(np); 6062306a36Sopenharmony_ci if (!mapped_l2_edac_addr) { 6162306a36Sopenharmony_ci pr_err("Unable to find L2 ECC mapping in dtb\n"); 6262306a36Sopenharmony_ci return; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (!sys_manager_base_addr) { 6662306a36Sopenharmony_ci pr_err("System Manager not mapped for L2 ECC\n"); 6762306a36Sopenharmony_ci goto exit; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci /* Clear any pending IRQs */ 7062306a36Sopenharmony_ci writel(A10_SYSMGR_MPU_CLEAR_L2_ECC, (sys_manager_base_addr + 7162306a36Sopenharmony_ci A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST)); 7262306a36Sopenharmony_ci /* Enable ECC */ 7362306a36Sopenharmony_ci writel(A10_SYSMGR_ECC_INTMASK_CLR_L2, sys_manager_base_addr + 7462306a36Sopenharmony_ci A10_SYSMGR_ECC_INTMASK_CLR_OFST); 7562306a36Sopenharmony_ci writel(A10_MPU_CTRL_L2_ECC_EN, mapped_l2_edac_addr + 7662306a36Sopenharmony_ci A10_MPU_CTRL_L2_ECC_OFST); 7762306a36Sopenharmony_ciexit: 7862306a36Sopenharmony_ci iounmap(mapped_l2_edac_addr); 7962306a36Sopenharmony_ci} 80