~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-socfpga/ocram.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php