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