Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright Altera Corporation (C) 2016. All rights reserved.
0004  */
0005 #include <linux/delay.h>
0006 #include <linux/io.h>
0007 #include <linux/genalloc.h>
0008 #include <linux/module.h>
0009 #include <linux/of_address.h>
0010 #include <linux/of_platform.h>
0011 
0012 #include "core.h"
0013 
0014 #define ALTR_OCRAM_CLEAR_ECC          0x00000018
0015 #define ALTR_OCRAM_ECC_EN             0x00000019
0016 
0017 void socfpga_init_ocram_ecc(void)
0018 {
0019     struct device_node *np;
0020     void __iomem *mapped_ocr_edac_addr;
0021 
0022     /* Find the OCRAM EDAC device tree node */
0023     np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc");
0024     if (!np) {
0025         pr_err("Unable to find socfpga-ocram-ecc\n");
0026         return;
0027     }
0028 
0029     mapped_ocr_edac_addr = of_iomap(np, 0);
0030     of_node_put(np);
0031     if (!mapped_ocr_edac_addr) {
0032         pr_err("Unable to map OCRAM ecc regs.\n");
0033         return;
0034     }
0035 
0036     /* Clear any pending OCRAM ECC interrupts, then enable ECC */
0037     writel(ALTR_OCRAM_CLEAR_ECC, mapped_ocr_edac_addr);
0038     writel(ALTR_OCRAM_ECC_EN, mapped_ocr_edac_addr);
0039 
0040     iounmap(mapped_ocr_edac_addr);
0041 }
0042 
0043 /* Arria10 OCRAM Section */
0044 #define ALTR_A10_ECC_CTRL_OFST          0x08
0045 #define ALTR_A10_OCRAM_ECC_EN_CTL       (BIT(1) | BIT(0))
0046 #define ALTR_A10_ECC_INITA              BIT(16)
0047 
0048 #define ALTR_A10_ECC_INITSTAT_OFST      0x0C
0049 #define ALTR_A10_ECC_INITCOMPLETEA      BIT(0)
0050 #define ALTR_A10_ECC_INITCOMPLETEB      BIT(8)
0051 
0052 #define ALTR_A10_ECC_ERRINTEN_OFST      0x10
0053 #define ALTR_A10_ECC_SERRINTEN          BIT(0)
0054 
0055 #define ALTR_A10_ECC_INTSTAT_OFST       0x20
0056 #define ALTR_A10_ECC_SERRPENA           BIT(0)
0057 #define ALTR_A10_ECC_DERRPENA           BIT(8)
0058 #define ALTR_A10_ECC_ERRPENA_MASK       (ALTR_A10_ECC_SERRPENA | \
0059                      ALTR_A10_ECC_DERRPENA)
0060 /* ECC Manager Defines */
0061 #define A10_SYSMGR_ECC_INTMASK_SET_OFST   0x94
0062 #define A10_SYSMGR_ECC_INTMASK_CLR_OFST   0x98
0063 #define A10_SYSMGR_ECC_INTMASK_OCRAM      BIT(1)
0064 
0065 #define ALTR_A10_ECC_INIT_WATCHDOG_10US   10000
0066 
0067 static inline void ecc_set_bits(u32 bit_mask, void __iomem *ioaddr)
0068 {
0069     u32 value = readl(ioaddr);
0070 
0071     value |= bit_mask;
0072     writel(value, ioaddr);
0073 }
0074 
0075 static inline void ecc_clear_bits(u32 bit_mask, void __iomem *ioaddr)
0076 {
0077     u32 value = readl(ioaddr);
0078 
0079     value &= ~bit_mask;
0080     writel(value, ioaddr);
0081 }
0082 
0083 static inline int ecc_test_bits(u32 bit_mask, void __iomem *ioaddr)
0084 {
0085     u32 value = readl(ioaddr);
0086 
0087     return (value & bit_mask) ? 1 : 0;
0088 }
0089 
0090 /*
0091  * This function uses the memory initialization block in the Arria10 ECC
0092  * controller to initialize/clear the entire memory data and ECC data.
0093  */
0094 static int altr_init_memory_port(void __iomem *ioaddr)
0095 {
0096     int limit = ALTR_A10_ECC_INIT_WATCHDOG_10US;
0097 
0098     ecc_set_bits(ALTR_A10_ECC_INITA, (ioaddr + ALTR_A10_ECC_CTRL_OFST));
0099     while (limit--) {
0100         if (ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
0101                   (ioaddr + ALTR_A10_ECC_INITSTAT_OFST)))
0102             break;
0103         udelay(1);
0104     }
0105     if (limit < 0)
0106         return -EBUSY;
0107 
0108     /* Clear any pending ECC interrupts */
0109     writel(ALTR_A10_ECC_ERRPENA_MASK,
0110            (ioaddr + ALTR_A10_ECC_INTSTAT_OFST));
0111 
0112     return 0;
0113 }
0114 
0115 void socfpga_init_arria10_ocram_ecc(void)
0116 {
0117     struct device_node *np;
0118     int ret = 0;
0119     void __iomem *ecc_block_base;
0120 
0121     if (!sys_manager_base_addr) {
0122         pr_err("SOCFPGA: sys-mgr is not initialized\n");
0123         return;
0124     }
0125 
0126     /* Find the OCRAM EDAC device tree node */
0127     np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-ocram-ecc");
0128     if (!np) {
0129         pr_err("Unable to find socfpga-a10-ocram-ecc\n");
0130         return;
0131     }
0132 
0133     /* Map the ECC Block */
0134     ecc_block_base = of_iomap(np, 0);
0135     of_node_put(np);
0136     if (!ecc_block_base) {
0137         pr_err("Unable to map OCRAM ECC block\n");
0138         return;
0139     }
0140 
0141     /* Disable ECC */
0142     writel(ALTR_A10_OCRAM_ECC_EN_CTL,
0143            sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_SET_OFST);
0144     ecc_clear_bits(ALTR_A10_ECC_SERRINTEN,
0145                (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
0146     ecc_clear_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
0147                (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
0148 
0149     /* Ensure all writes complete */
0150     wmb();
0151 
0152     /* Use HW initialization block to initialize memory for ECC */
0153     ret = altr_init_memory_port(ecc_block_base);
0154     if (ret) {
0155         pr_err("ECC: cannot init OCRAM PORTA memory\n");
0156         goto exit;
0157     }
0158 
0159     /* Enable ECC */
0160     ecc_set_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
0161              (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
0162     ecc_set_bits(ALTR_A10_ECC_SERRINTEN,
0163              (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
0164     writel(ALTR_A10_OCRAM_ECC_EN_CTL,
0165            sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_CLR_OFST);
0166 
0167     /* Ensure all writes complete */
0168     wmb();
0169 exit:
0170     iounmap(ecc_block_base);
0171 }