root/arch/arm/mach-socfpga/ocram.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. socfpga_init_ocram_ecc
  2. ecc_set_bits
  3. ecc_clear_bits
  4. ecc_test_bits
  5. altr_init_memory_port
  6. socfpga_init_arria10_ocram_ecc

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright Altera Corporation (C) 2016. All rights reserved.
   4  */
   5 #include <linux/delay.h>
   6 #include <linux/io.h>
   7 #include <linux/genalloc.h>
   8 #include <linux/module.h>
   9 #include <linux/of_address.h>
  10 #include <linux/of_platform.h>
  11 
  12 #include "core.h"
  13 
  14 #define ALTR_OCRAM_CLEAR_ECC          0x00000018
  15 #define ALTR_OCRAM_ECC_EN             0x00000019
  16 
  17 void socfpga_init_ocram_ecc(void)
  18 {
  19         struct device_node *np;
  20         void __iomem *mapped_ocr_edac_addr;
  21 
  22         /* Find the OCRAM EDAC device tree node */
  23         np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc");
  24         if (!np) {
  25                 pr_err("Unable to find socfpga-ocram-ecc\n");
  26                 return;
  27         }
  28 
  29         mapped_ocr_edac_addr = of_iomap(np, 0);
  30         of_node_put(np);
  31         if (!mapped_ocr_edac_addr) {
  32                 pr_err("Unable to map OCRAM ecc regs.\n");
  33                 return;
  34         }
  35 
  36         /* Clear any pending OCRAM ECC interrupts, then enable ECC */
  37         writel(ALTR_OCRAM_CLEAR_ECC, mapped_ocr_edac_addr);
  38         writel(ALTR_OCRAM_ECC_EN, mapped_ocr_edac_addr);
  39 
  40         iounmap(mapped_ocr_edac_addr);
  41 }
  42 
  43 /* Arria10 OCRAM Section */
  44 #define ALTR_A10_ECC_CTRL_OFST          0x08
  45 #define ALTR_A10_OCRAM_ECC_EN_CTL       (BIT(1) | BIT(0))
  46 #define ALTR_A10_ECC_INITA              BIT(16)
  47 
  48 #define ALTR_A10_ECC_INITSTAT_OFST      0x0C
  49 #define ALTR_A10_ECC_INITCOMPLETEA      BIT(0)
  50 #define ALTR_A10_ECC_INITCOMPLETEB      BIT(8)
  51 
  52 #define ALTR_A10_ECC_ERRINTEN_OFST      0x10
  53 #define ALTR_A10_ECC_SERRINTEN          BIT(0)
  54 
  55 #define ALTR_A10_ECC_INTSTAT_OFST       0x20
  56 #define ALTR_A10_ECC_SERRPENA           BIT(0)
  57 #define ALTR_A10_ECC_DERRPENA           BIT(8)
  58 #define ALTR_A10_ECC_ERRPENA_MASK       (ALTR_A10_ECC_SERRPENA | \
  59                                          ALTR_A10_ECC_DERRPENA)
  60 /* ECC Manager Defines */
  61 #define A10_SYSMGR_ECC_INTMASK_SET_OFST   0x94
  62 #define A10_SYSMGR_ECC_INTMASK_CLR_OFST   0x98
  63 #define A10_SYSMGR_ECC_INTMASK_OCRAM      BIT(1)
  64 
  65 #define ALTR_A10_ECC_INIT_WATCHDOG_10US   10000
  66 
  67 static inline void ecc_set_bits(u32 bit_mask, void __iomem *ioaddr)
  68 {
  69         u32 value = readl(ioaddr);
  70 
  71         value |= bit_mask;
  72         writel(value, ioaddr);
  73 }
  74 
  75 static inline void ecc_clear_bits(u32 bit_mask, void __iomem *ioaddr)
  76 {
  77         u32 value = readl(ioaddr);
  78 
  79         value &= ~bit_mask;
  80         writel(value, ioaddr);
  81 }
  82 
  83 static inline int ecc_test_bits(u32 bit_mask, void __iomem *ioaddr)
  84 {
  85         u32 value = readl(ioaddr);
  86 
  87         return (value & bit_mask) ? 1 : 0;
  88 }
  89 
  90 /*
  91  * This function uses the memory initialization block in the Arria10 ECC
  92  * controller to initialize/clear the entire memory data and ECC data.
  93  */
  94 static int altr_init_memory_port(void __iomem *ioaddr)
  95 {
  96         int limit = ALTR_A10_ECC_INIT_WATCHDOG_10US;
  97 
  98         ecc_set_bits(ALTR_A10_ECC_INITA, (ioaddr + ALTR_A10_ECC_CTRL_OFST));
  99         while (limit--) {
 100                 if (ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
 101                                   (ioaddr + ALTR_A10_ECC_INITSTAT_OFST)))
 102                         break;
 103                 udelay(1);
 104         }
 105         if (limit < 0)
 106                 return -EBUSY;
 107 
 108         /* Clear any pending ECC interrupts */
 109         writel(ALTR_A10_ECC_ERRPENA_MASK,
 110                (ioaddr + ALTR_A10_ECC_INTSTAT_OFST));
 111 
 112         return 0;
 113 }
 114 
 115 void socfpga_init_arria10_ocram_ecc(void)
 116 {
 117         struct device_node *np;
 118         int ret = 0;
 119         void __iomem *ecc_block_base;
 120 
 121         if (!sys_manager_base_addr) {
 122                 pr_err("SOCFPGA: sys-mgr is not initialized\n");
 123                 return;
 124         }
 125 
 126         /* Find the OCRAM EDAC device tree node */
 127         np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-ocram-ecc");
 128         if (!np) {
 129                 pr_err("Unable to find socfpga-a10-ocram-ecc\n");
 130                 return;
 131         }
 132 
 133         /* Map the ECC Block */
 134         ecc_block_base = of_iomap(np, 0);
 135         of_node_put(np);
 136         if (!ecc_block_base) {
 137                 pr_err("Unable to map OCRAM ECC block\n");
 138                 return;
 139         }
 140 
 141         /* Disable ECC */
 142         writel(ALTR_A10_OCRAM_ECC_EN_CTL,
 143                sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_SET_OFST);
 144         ecc_clear_bits(ALTR_A10_ECC_SERRINTEN,
 145                        (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
 146         ecc_clear_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
 147                        (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
 148 
 149         /* Ensure all writes complete */
 150         wmb();
 151 
 152         /* Use HW initialization block to initialize memory for ECC */
 153         ret = altr_init_memory_port(ecc_block_base);
 154         if (ret) {
 155                 pr_err("ECC: cannot init OCRAM PORTA memory\n");
 156                 goto exit;
 157         }
 158 
 159         /* Enable ECC */
 160         ecc_set_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
 161                      (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
 162         ecc_set_bits(ALTR_A10_ECC_SERRINTEN,
 163                      (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
 164         writel(ALTR_A10_OCRAM_ECC_EN_CTL,
 165                sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_CLR_OFST);
 166 
 167         /* Ensure all writes complete */
 168         wmb();
 169 exit:
 170         iounmap(ecc_block_base);
 171 }

/* [<][>][^][v][top][bottom][index][help] */