^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Synopsys DDR ECC Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * This driver is based on ppc4xx_edac.c drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 - 2014 Xilinx, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This program is free software: you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * the Free Software Foundation, either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * for more details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/edac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Number of cs_rows needed per memory controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SYNPS_EDAC_NR_CSROWS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Number of channels per memory controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SYNPS_EDAC_NR_CHANS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Granularity of reported error in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SYNPS_EDAC_ERR_GRAIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SYNPS_EDAC_MSG_SIZE 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define SYNPS_EDAC_MOD_STRING "synps_edac"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SYNPS_EDAC_MOD_VER "1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Synopsys DDR memory controller registers that are relevant to ECC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define CTRL_OFST 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define T_ZQ_OFST 0xA4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* ECC control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ECC_CTRL_OFST 0xC4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* ECC log register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CE_LOG_OFST 0xC8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* ECC address register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define CE_ADDR_OFST 0xCC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* ECC data[31:0] register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CE_DATA_31_0_OFST 0xD0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Uncorrectable error info registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define UE_LOG_OFST 0xDC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define UE_ADDR_OFST 0xE0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define UE_DATA_31_0_OFST 0xE4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define STAT_OFST 0xF0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define SCRUB_OFST 0xF4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* Control register bit field definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define CTRL_BW_MASK 0xC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CTRL_BW_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define DDRCTL_WDTH_16 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define DDRCTL_WDTH_32 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* ZQ register bit field definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define T_ZQ_DDRMODE_MASK 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* ECC control register bit field definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define ECC_CTRL_CLR_CE_ERR 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ECC_CTRL_CLR_UE_ERR 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* ECC correctable/uncorrectable error log register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define LOG_VALID 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define CE_LOG_BITPOS_MASK 0xFE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define CE_LOG_BITPOS_SHIFT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* ECC correctable/uncorrectable error address register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define ADDR_COL_MASK 0xFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define ADDR_ROW_MASK 0xFFFF000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define ADDR_ROW_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define ADDR_BANK_MASK 0x70000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define ADDR_BANK_SHIFT 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* ECC statistic register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define STAT_UECNT_MASK 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define STAT_CECNT_MASK 0xFF00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define STAT_CECNT_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* ECC scrub register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define SCRUB_MODE_MASK 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SCRUB_MODE_SECDED 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* DDR ECC Quirks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define DDR_ECC_INTR_SUPPORT BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define DDR_ECC_DATA_POISON_SUPPORT BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* ECC Configuration Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define ECC_CFG0_OFST 0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define ECC_CFG1_OFST 0x74
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* ECC Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define ECC_STAT_OFST 0x78
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* ECC Clear Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define ECC_CLR_OFST 0x7C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* ECC Error count Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define ECC_ERRCNT_OFST 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* ECC Corrected Error Address Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define ECC_CEADDR0_OFST 0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define ECC_CEADDR1_OFST 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* ECC Syndrome Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define ECC_CSYND0_OFST 0x8C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define ECC_CSYND1_OFST 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define ECC_CSYND2_OFST 0x94
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* ECC Bit Mask0 Address Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define ECC_BITMASK0_OFST 0x98
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define ECC_BITMASK1_OFST 0x9C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define ECC_BITMASK2_OFST 0xA0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* ECC UnCorrected Error Address Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define ECC_UEADDR0_OFST 0xA4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define ECC_UEADDR1_OFST 0xA8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* ECC Syndrome Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define ECC_UESYND0_OFST 0xAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define ECC_UESYND1_OFST 0xB0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define ECC_UESYND2_OFST 0xB4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* ECC Poison Address Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define ECC_POISON0_OFST 0xB8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define ECC_POISON1_OFST 0xBC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define ECC_ADDRMAP0_OFFSET 0x200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Control register bitfield definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define ECC_CTRL_BUSWIDTH_MASK 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define ECC_CTRL_BUSWIDTH_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* DDR Control Register width definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define DDRCTL_EWDTH_16 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define DDRCTL_EWDTH_32 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define DDRCTL_EWDTH_64 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* ECC status register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define ECC_STAT_UECNT_MASK 0xF0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define ECC_STAT_UECNT_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define ECC_STAT_CECNT_MASK 0xF00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define ECC_STAT_CECNT_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define ECC_STAT_BITNUM_MASK 0x7F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* DDR QOS Interrupt register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define DDR_QOS_IRQ_STAT_OFST 0x20200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define DDR_QOSUE_MASK 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define DDR_QOSCE_MASK 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define ECC_CE_UE_INTR_MASK 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define DDR_QOS_IRQ_EN_OFST 0x20208
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define DDR_QOS_IRQ_DB_OFST 0x2020C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* ECC Corrected Error Register Mask and Shifts*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define ECC_CEADDR0_RW_MASK 0x3FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define ECC_CEADDR0_RNK_MASK BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define ECC_CEADDR1_BNKGRP_MASK 0x3000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define ECC_CEADDR1_BNKNR_MASK 0x70000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define ECC_CEADDR1_BLKNR_MASK 0xFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define ECC_CEADDR1_BNKGRP_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define ECC_CEADDR1_BNKNR_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* ECC Poison register shifts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define ECC_POISON0_RANK_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define ECC_POISON0_RANK_MASK BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define ECC_POISON0_COLUMN_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define ECC_POISON0_COLUMN_MASK 0xFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define ECC_POISON1_BG_SHIFT 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define ECC_POISON1_BG_MASK 0x30000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define ECC_POISON1_BANKNR_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define ECC_POISON1_BANKNR_MASK 0x7000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define ECC_POISON1_ROW_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define ECC_POISON1_ROW_MASK 0x3FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* DDR Memory type defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define MEM_TYPE_DDR3 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define MEM_TYPE_LPDDR3 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define MEM_TYPE_DDR2 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define MEM_TYPE_DDR4 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define MEM_TYPE_LPDDR4 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* DDRC Software control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define DDRC_SWCTL 0x320
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* DDRC ECC CE & UE poison mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define ECC_CEPOISON_MASK 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #define ECC_UEPOISON_MASK 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* DDRC Device config masks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #define DDRC_MSTR_CFG_MASK 0xC0000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define DDRC_MSTR_CFG_SHIFT 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #define DDRC_MSTR_CFG_X4_MASK 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #define DDRC_MSTR_CFG_X8_MASK 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #define DDRC_MSTR_CFG_X16_MASK 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #define DDRC_MSTR_CFG_X32_MASK 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define DDR_MAX_ROW_SHIFT 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #define DDR_MAX_COL_SHIFT 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #define DDR_MAX_BANK_SHIFT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #define DDR_MAX_BANKGRP_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define ROW_MAX_VAL_MASK 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define COL_MAX_VAL_MASK 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define BANK_MAX_VAL_MASK 0x1F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define BANKGRP_MAX_VAL_MASK 0x1F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define RANK_MAX_VAL_MASK 0x1F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define ROW_B0_BASE 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define ROW_B1_BASE 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #define ROW_B2_BASE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #define ROW_B3_BASE 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) #define ROW_B4_BASE 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #define ROW_B5_BASE 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #define ROW_B6_BASE 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define ROW_B7_BASE 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define ROW_B8_BASE 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #define ROW_B9_BASE 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #define ROW_B10_BASE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #define ROW_B11_BASE 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define ROW_B12_BASE 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define ROW_B13_BASE 19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define ROW_B14_BASE 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define ROW_B15_BASE 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define ROW_B16_BASE 22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #define ROW_B17_BASE 23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define COL_B2_BASE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #define COL_B3_BASE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #define COL_B4_BASE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #define COL_B5_BASE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #define COL_B6_BASE 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) #define COL_B7_BASE 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #define COL_B8_BASE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #define COL_B9_BASE 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) #define COL_B10_BASE 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) #define COL_B11_BASE 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) #define COL_B12_BASE 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) #define COL_B13_BASE 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) #define BANK_B0_BASE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #define BANK_B1_BASE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #define BANK_B2_BASE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #define BANKGRP_B0_BASE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #define BANKGRP_B1_BASE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #define RANK_B0_BASE 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * struct ecc_error_info - ECC error log information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * @row: Row number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * @col: Column number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * @bank: Bank number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * @bitpos: Bit position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @data: Data causing the error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * @bankgrpnr: Bank group number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * @blknr: Block number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct ecc_error_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u32 row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u32 col;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) u32 bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) u32 bitpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u32 bankgrpnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u32 blknr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * struct synps_ecc_status - ECC status information to report.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * @ce_cnt: Correctable error count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @ue_cnt: Uncorrectable error count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @ceinfo: Correctable error log information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * @ueinfo: Uncorrectable error log information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct synps_ecc_status {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u32 ce_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u32 ue_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct ecc_error_info ceinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct ecc_error_info ueinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * struct synps_edac_priv - DDR memory controller private instance data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * @baseaddr: Base address of the DDR controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * @message: Buffer for framing the event specific info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * @stat: ECC status information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * @p_data: Platform data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * @ce_cnt: Correctable Error count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * @ue_cnt: Uncorrectable Error count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * @poison_addr: Data poison address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * @row_shift: Bit shifts for row bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * @col_shift: Bit shifts for column bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * @bank_shift: Bit shifts for bank bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * @bankgrp_shift: Bit shifts for bank group bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * @rank_shift: Bit shifts for rank bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct synps_edac_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) void __iomem *baseaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) char message[SYNPS_EDAC_MSG_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct synps_ecc_status stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) const struct synps_platform_data *p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) u32 ce_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u32 ue_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ulong poison_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) u32 row_shift[18];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) u32 col_shift[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) u32 bank_shift[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u32 bankgrp_shift[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) u32 rank_shift[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * struct synps_platform_data - synps platform data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * @get_error_info: Get EDAC error info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * @get_mtype: Get mtype.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * @get_dtype: Get dtype.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * @get_ecc_state: Get ECC state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * @quirks: To differentiate IPs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct synps_platform_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int (*get_error_info)(struct synps_edac_priv *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) enum mem_type (*get_mtype)(const void __iomem *base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) enum dev_type (*get_dtype)(const void __iomem *base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) bool (*get_ecc_state)(void __iomem *base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * zynq_get_error_info - Get the current ECC error info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * @priv: DDR memory controller private instance data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * Return: one if there is no error, otherwise zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int zynq_get_error_info(struct synps_edac_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct synps_ecc_status *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u32 regval, clearval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) base = priv->baseaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) p = &priv->stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) regval = readl(base + STAT_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (!regval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) p->ce_cnt = (regval & STAT_CECNT_MASK) >> STAT_CECNT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) p->ue_cnt = regval & STAT_UECNT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) regval = readl(base + CE_LOG_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!(p->ce_cnt && (regval & LOG_VALID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) goto ue_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) p->ceinfo.bitpos = (regval & CE_LOG_BITPOS_MASK) >> CE_LOG_BITPOS_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) regval = readl(base + CE_ADDR_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) p->ceinfo.row = (regval & ADDR_ROW_MASK) >> ADDR_ROW_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) p->ceinfo.col = regval & ADDR_COL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) p->ceinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) p->ceinfo.data = readl(base + CE_DATA_31_0_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) edac_dbg(3, "CE bit position: %d data: %d\n", p->ceinfo.bitpos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) p->ceinfo.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) clearval = ECC_CTRL_CLR_CE_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ue_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) regval = readl(base + UE_LOG_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!(p->ue_cnt && (regval & LOG_VALID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) regval = readl(base + UE_ADDR_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) p->ueinfo.row = (regval & ADDR_ROW_MASK) >> ADDR_ROW_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) p->ueinfo.col = regval & ADDR_COL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) p->ueinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) p->ueinfo.data = readl(base + UE_DATA_31_0_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) clearval |= ECC_CTRL_CLR_UE_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) writel(clearval, base + ECC_CTRL_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) writel(0x0, base + ECC_CTRL_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * zynqmp_get_error_info - Get the current ECC error info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * @priv: DDR memory controller private instance data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * Return: one if there is no error otherwise returns zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int zynqmp_get_error_info(struct synps_edac_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct synps_ecc_status *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) u32 regval, clearval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) base = priv->baseaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) p = &priv->stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) regval = readl(base + ECC_STAT_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!regval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (!p->ce_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto ue_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) regval = readl(base + ECC_CEADDR0_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) p->ceinfo.row = (regval & ECC_CEADDR0_RW_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) regval = readl(base + ECC_CEADDR1_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) p->ceinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ECC_CEADDR1_BNKNR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) p->ceinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ECC_CEADDR1_BNKGRP_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) p->ceinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) p->ceinfo.data = readl(base + ECC_CSYND0_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) readl(base + ECC_CSYND2_OFST));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ue_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!p->ue_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) regval = readl(base + ECC_UEADDR0_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) p->ueinfo.row = (regval & ECC_CEADDR0_RW_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) regval = readl(base + ECC_UEADDR1_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) p->ueinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ECC_CEADDR1_BNKGRP_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) p->ueinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ECC_CEADDR1_BNKNR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) p->ueinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) p->ueinfo.data = readl(base + ECC_UESYND0_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) clearval |= ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) writel(clearval, base + ECC_CLR_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) writel(0x0, base + ECC_CLR_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * handle_error - Handle Correctable and Uncorrectable errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * @mci: EDAC memory controller instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * @p: Synopsys ECC status structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * Handles ECC correctable and uncorrectable errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct ecc_error_info *pinf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (p->ce_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) pinf = &p->ceinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) "DDR ECC error type:%s Row %d Bank %d BankGroup Number %d Block Number %d Bit Position: %d Data: 0x%08x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) "CE", pinf->row, pinf->bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) pinf->bankgrpnr, pinf->blknr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) pinf->bitpos, pinf->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) "DDR ECC error type:%s Row %d Bank %d Col %d Bit Position: %d Data: 0x%08x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) "CE", pinf->row, pinf->bank, pinf->col,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) pinf->bitpos, pinf->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) p->ce_cnt, 0, 0, 0, 0, 0, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) priv->message, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (p->ue_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) pinf = &p->ueinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) "DDR ECC error type :%s Row %d Bank %d BankGroup Number %d Block Number %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) "UE", pinf->row, pinf->bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) pinf->bankgrpnr, pinf->blknr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) "DDR ECC error type :%s Row %d Bank %d Col %d ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) "UE", pinf->row, pinf->bank, pinf->col);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) p->ue_cnt, 0, 0, 0, 0, 0, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) priv->message, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) memset(p, 0, sizeof(*p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * intr_handler - Interrupt Handler for ECC interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * @irq: IRQ number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * @dev_id: Device ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static irqreturn_t intr_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) const struct synps_platform_data *p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct mem_ctl_info *mci = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct synps_edac_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int status, regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) p_data = priv->p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) regval = readl(priv->baseaddr + DDR_QOS_IRQ_STAT_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) regval &= (DDR_QOSCE_MASK | DDR_QOSUE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!(regval & ECC_CE_UE_INTR_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) status = p_data->get_error_info(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) priv->ce_cnt += priv->stat.ce_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) priv->ue_cnt += priv->stat.ue_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) handle_error(mci, &priv->stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) edac_dbg(3, "Total error count CE %d UE %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) priv->ce_cnt, priv->ue_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) writel(regval, priv->baseaddr + DDR_QOS_IRQ_STAT_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * check_errors - Check controller for ECC errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * @mci: EDAC memory controller instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * Check and post ECC errors. Called by the polling thread.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static void check_errors(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) const struct synps_platform_data *p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct synps_edac_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) p_data = priv->p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) status = p_data->get_error_info(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) priv->ce_cnt += priv->stat.ce_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) priv->ue_cnt += priv->stat.ue_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) handle_error(mci, &priv->stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) edac_dbg(3, "Total error count CE %d UE %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) priv->ce_cnt, priv->ue_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * zynq_get_dtype - Return the controller memory width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * @base: DDR memory controller base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * Get the EDAC device type width appropriate for the current controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * Return: a device type width enumeration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static enum dev_type zynq_get_dtype(const void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) enum dev_type dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) u32 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) width = readl(base + CTRL_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) width = (width & CTRL_BW_MASK) >> CTRL_BW_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) switch (width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case DDRCTL_WDTH_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) dt = DEV_X2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) case DDRCTL_WDTH_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) dt = DEV_X4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dt = DEV_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * zynqmp_get_dtype - Return the controller memory width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * @base: DDR memory controller base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * Get the EDAC device type width appropriate for the current controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * Return: a device type width enumeration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static enum dev_type zynqmp_get_dtype(const void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) enum dev_type dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) u32 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) width = readl(base + CTRL_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) width = (width & ECC_CTRL_BUSWIDTH_MASK) >> ECC_CTRL_BUSWIDTH_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) switch (width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) case DDRCTL_EWDTH_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) dt = DEV_X2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) case DDRCTL_EWDTH_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) dt = DEV_X4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case DDRCTL_EWDTH_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) dt = DEV_X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dt = DEV_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * zynq_get_ecc_state - Return the controller ECC enable/disable status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * @base: DDR memory controller base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * Get the ECC enable/disable status of the controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * Return: true if enabled, otherwise false.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static bool zynq_get_ecc_state(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) enum dev_type dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) u32 ecctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) dt = zynq_get_dtype(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (dt == DEV_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) ecctype = readl(base + SCRUB_OFST) & SCRUB_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if ((ecctype == SCRUB_MODE_SECDED) && (dt == DEV_X2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * zynqmp_get_ecc_state - Return the controller ECC enable/disable status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * @base: DDR memory controller base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * Get the ECC enable/disable status for the controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * Return: a ECC status boolean i.e true/false - enabled/disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static bool zynqmp_get_ecc_state(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) enum dev_type dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) u32 ecctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) dt = zynqmp_get_dtype(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (dt == DEV_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ecctype = readl(base + ECC_CFG0_OFST) & SCRUB_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if ((ecctype == SCRUB_MODE_SECDED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ((dt == DEV_X2) || (dt == DEV_X4) || (dt == DEV_X8)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * get_memsize - Read the size of the attached memory device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * Return: the memory size in bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static u32 get_memsize(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct sysinfo inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) si_meminfo(&inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return inf.totalram * inf.mem_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * zynq_get_mtype - Return the controller memory type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * @base: Synopsys ECC status structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * Get the EDAC memory type appropriate for the current controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * Return: a memory type enumeration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static enum mem_type zynq_get_mtype(const void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) enum mem_type mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) u32 memtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) memtype = readl(base + T_ZQ_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (memtype & T_ZQ_DDRMODE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) mt = MEM_DDR3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) mt = MEM_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * zynqmp_get_mtype - Returns controller memory type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * @base: Synopsys ECC status structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * Get the EDAC memory type appropriate for the current controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * Return: a memory type enumeration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static enum mem_type zynqmp_get_mtype(const void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) enum mem_type mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) u32 memtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) memtype = readl(base + CTRL_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if ((memtype & MEM_TYPE_DDR3) || (memtype & MEM_TYPE_LPDDR3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) mt = MEM_DDR3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) else if (memtype & MEM_TYPE_DDR2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) mt = MEM_RDDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) else if ((memtype & MEM_TYPE_LPDDR4) || (memtype & MEM_TYPE_DDR4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) mt = MEM_DDR4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) mt = MEM_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * init_csrows - Initialize the csrow data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * @mci: EDAC memory controller instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * Initialize the chip select rows associated with the EDAC memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * controller instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static void init_csrows(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) const struct synps_platform_data *p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) struct csrow_info *csi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) struct dimm_info *dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) u32 size, row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) p_data = priv->p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) for (row = 0; row < mci->nr_csrows; row++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) csi = mci->csrows[row];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) size = get_memsize();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) for (j = 0; j < csi->nr_channels; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) dimm = csi->channels[j]->dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) dimm->edac_mode = EDAC_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) dimm->mtype = p_data->get_mtype(priv->baseaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) dimm->grain = SYNPS_EDAC_ERR_GRAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) dimm->dtype = p_data->get_dtype(priv->baseaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * mc_init - Initialize one driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * @mci: EDAC memory controller instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * @pdev: platform device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * Perform initialization of the EDAC memory controller instance and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * related driver-private data associated with the memory controller the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * instance is bound to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) struct synps_edac_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) mci->pdev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) platform_set_drvdata(pdev, mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* Initialize controller capabilities and configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) mci->mtype_cap = MEM_FLAG_DDR3 | MEM_FLAG_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mci->scrub_cap = SCRUB_HW_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) mci->scrub_mode = SCRUB_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mci->edac_cap = EDAC_FLAG_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) mci->ctl_name = "synps_ddr_controller";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) mci->dev_name = SYNPS_EDAC_MOD_STRING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) mci->mod_name = SYNPS_EDAC_MOD_VER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) edac_op_state = EDAC_OPSTATE_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) edac_op_state = EDAC_OPSTATE_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) mci->edac_check = check_errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) mci->ctl_page_to_phys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) init_csrows(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static void enable_intr(struct synps_edac_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) /* Enable UE/CE Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) priv->baseaddr + DDR_QOS_IRQ_EN_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static void disable_intr(struct synps_edac_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* Disable UE/CE Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) priv->baseaddr + DDR_QOS_IRQ_DB_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static int setup_irq(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) int ret, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) edac_printk(KERN_ERR, EDAC_MC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) "No IRQ %d in DT\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) ret = devm_request_irq(&pdev->dev, irq, intr_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 0, dev_name(&pdev->dev), mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) edac_printk(KERN_ERR, EDAC_MC, "Failed to request IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) enable_intr(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static const struct synps_platform_data zynq_edac_def = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .get_error_info = zynq_get_error_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .get_mtype = zynq_get_mtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .get_dtype = zynq_get_dtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .get_ecc_state = zynq_get_ecc_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .quirks = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static const struct synps_platform_data zynqmp_edac_def = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .get_error_info = zynqmp_get_error_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .get_mtype = zynqmp_get_mtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) .get_dtype = zynqmp_get_dtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) .get_ecc_state = zynqmp_get_ecc_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .quirks = (DDR_ECC_INTR_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) | DDR_ECC_DATA_POISON_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static const struct of_device_id synps_edac_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .compatible = "xlnx,zynq-ddrc-a05",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) .data = (void *)&zynq_edac_def
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) .compatible = "xlnx,zynqmp-ddrc-2.40a",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) .data = (void *)&zynqmp_edac_def
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) /* end of table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) MODULE_DEVICE_TABLE(of, synps_edac_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) #define to_mci(k) container_of(k, struct mem_ctl_info, dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * ddr_poison_setup - Update poison registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * @priv: DDR memory controller private instance data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * Update poison registers as per DDR mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * Return: none.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static void ddr_poison_setup(struct synps_edac_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ulong hif_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) hif_addr = priv->poison_addr >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (priv->row_shift[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) row |= (((hif_addr >> priv->row_shift[index]) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) BIT(0)) << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) for (index = 0; index < DDR_MAX_COL_SHIFT; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (priv->col_shift[index] || index < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) col |= (((hif_addr >> priv->col_shift[index]) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) BIT(0)) << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (priv->bank_shift[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) bank |= (((hif_addr >> priv->bank_shift[index]) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) BIT(0)) << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (priv->bankgrp_shift[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) bankgrp |= (((hif_addr >> priv->bankgrp_shift[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) & BIT(0)) << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (priv->rank_shift[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) rank = (hif_addr >> priv->rank_shift[0]) & BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) regval = (rank << ECC_POISON0_RANK_SHIFT) & ECC_POISON0_RANK_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) regval |= (col << ECC_POISON0_COLUMN_SHIFT) & ECC_POISON0_COLUMN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) writel(regval, priv->baseaddr + ECC_POISON0_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) regval = (bankgrp << ECC_POISON1_BG_SHIFT) & ECC_POISON1_BG_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) regval |= (bank << ECC_POISON1_BANKNR_SHIFT) & ECC_POISON1_BANKNR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) regval |= (row << ECC_POISON1_ROW_SHIFT) & ECC_POISON1_ROW_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) writel(regval, priv->baseaddr + ECC_POISON1_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static ssize_t inject_data_error_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) struct device_attribute *mattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct mem_ctl_info *mci = to_mci(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return sprintf(data, "Poison0 Addr: 0x%08x\n\rPoison1 Addr: 0x%08x\n\r"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) "Error injection Address: 0x%lx\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) readl(priv->baseaddr + ECC_POISON0_OFST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) readl(priv->baseaddr + ECC_POISON1_OFST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) priv->poison_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static ssize_t inject_data_error_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) struct device_attribute *mattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) const char *data, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct mem_ctl_info *mci = to_mci(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (kstrtoul(data, 0, &priv->poison_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ddr_poison_setup(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) static ssize_t inject_data_poison_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) struct device_attribute *mattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct mem_ctl_info *mci = to_mci(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return sprintf(data, "Data Poisoning: %s\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) (((readl(priv->baseaddr + ECC_CFG1_OFST)) & 0x3) == 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) ? ("Correctable Error") : ("UnCorrectable Error"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) static ssize_t inject_data_poison_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) struct device_attribute *mattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) const char *data, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct mem_ctl_info *mci = to_mci(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) writel(0, priv->baseaddr + DDRC_SWCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (strncmp(data, "CE", 2) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) writel(ECC_CEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) writel(ECC_UEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) writel(1, priv->baseaddr + DDRC_SWCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static DEVICE_ATTR_RW(inject_data_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) static DEVICE_ATTR_RW(inject_data_poison);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static int edac_create_sysfs_attributes(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) rc = device_create_file(&mci->dev, &dev_attr_inject_data_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) rc = device_create_file(&mci->dev, &dev_attr_inject_data_poison);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static void edac_remove_sysfs_attributes(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) device_remove_file(&mci->dev, &dev_attr_inject_data_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) device_remove_file(&mci->dev, &dev_attr_inject_data_poison);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static void setup_row_address_map(struct synps_edac_priv *priv, u32 *addrmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) u32 addrmap_row_b2_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) priv->row_shift[0] = (addrmap[5] & ROW_MAX_VAL_MASK) + ROW_B0_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) priv->row_shift[1] = ((addrmap[5] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ROW_MAX_VAL_MASK) + ROW_B1_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) addrmap_row_b2_10 = (addrmap[5] >> 16) & ROW_MAX_VAL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (addrmap_row_b2_10 != ROW_MAX_VAL_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) for (index = 2; index < 11; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) priv->row_shift[index] = addrmap_row_b2_10 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) index + ROW_B0_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) priv->row_shift[2] = (addrmap[9] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ROW_MAX_VAL_MASK) + ROW_B2_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) priv->row_shift[3] = ((addrmap[9] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ROW_MAX_VAL_MASK) + ROW_B3_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) priv->row_shift[4] = ((addrmap[9] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) ROW_MAX_VAL_MASK) + ROW_B4_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) priv->row_shift[5] = ((addrmap[9] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ROW_MAX_VAL_MASK) + ROW_B5_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) priv->row_shift[6] = (addrmap[10] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ROW_MAX_VAL_MASK) + ROW_B6_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) priv->row_shift[7] = ((addrmap[10] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ROW_MAX_VAL_MASK) + ROW_B7_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) priv->row_shift[8] = ((addrmap[10] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) ROW_MAX_VAL_MASK) + ROW_B8_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) priv->row_shift[9] = ((addrmap[10] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) ROW_MAX_VAL_MASK) + ROW_B9_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) priv->row_shift[10] = (addrmap[11] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) ROW_MAX_VAL_MASK) + ROW_B10_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) priv->row_shift[11] = (((addrmap[5] >> 24) & ROW_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) ROW_MAX_VAL_MASK) ? 0 : (((addrmap[5] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) ROW_MAX_VAL_MASK) + ROW_B11_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) priv->row_shift[12] = ((addrmap[6] & ROW_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) ROW_MAX_VAL_MASK) ? 0 : ((addrmap[6] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ROW_MAX_VAL_MASK) + ROW_B12_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) priv->row_shift[13] = (((addrmap[6] >> 8) & ROW_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) ROW_MAX_VAL_MASK) + ROW_B13_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) priv->row_shift[14] = (((addrmap[6] >> 16) & ROW_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) ROW_MAX_VAL_MASK) + ROW_B14_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) priv->row_shift[15] = (((addrmap[6] >> 24) & ROW_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) ROW_MAX_VAL_MASK) + ROW_B15_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) priv->row_shift[16] = ((addrmap[7] & ROW_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) ROW_MAX_VAL_MASK) ? 0 : ((addrmap[7] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) ROW_MAX_VAL_MASK) + ROW_B16_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) priv->row_shift[17] = (((addrmap[7] >> 8) & ROW_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) ROW_MAX_VAL_MASK) ? 0 : (((addrmap[7] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) ROW_MAX_VAL_MASK) + ROW_B17_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) static void setup_column_address_map(struct synps_edac_priv *priv, u32 *addrmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) u32 width, memtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) memtype = readl(priv->baseaddr + CTRL_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) width = (memtype & ECC_CTRL_BUSWIDTH_MASK) >> ECC_CTRL_BUSWIDTH_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) priv->col_shift[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) priv->col_shift[1] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) priv->col_shift[2] = (addrmap[2] & COL_MAX_VAL_MASK) + COL_B2_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) priv->col_shift[3] = ((addrmap[2] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) COL_MAX_VAL_MASK) + COL_B3_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) priv->col_shift[4] = (((addrmap[2] >> 16) & COL_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) COL_MAX_VAL_MASK) ? 0 : (((addrmap[2] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) COL_MAX_VAL_MASK) + COL_B4_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) priv->col_shift[5] = (((addrmap[2] >> 24) & COL_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) COL_MAX_VAL_MASK) ? 0 : (((addrmap[2] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) COL_MAX_VAL_MASK) + COL_B5_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) priv->col_shift[6] = ((addrmap[3] & COL_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) COL_MAX_VAL_MASK) ? 0 : ((addrmap[3] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) COL_MAX_VAL_MASK) + COL_B6_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) priv->col_shift[7] = (((addrmap[3] >> 8) & COL_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) COL_MAX_VAL_MASK) + COL_B7_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) priv->col_shift[8] = (((addrmap[3] >> 16) & COL_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) COL_MAX_VAL_MASK) + COL_B8_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) priv->col_shift[9] = (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) COL_MAX_VAL_MASK) + COL_B9_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (width == DDRCTL_EWDTH_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (memtype & MEM_TYPE_LPDDR3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) priv->col_shift[10] = ((addrmap[4] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) ((addrmap[4] & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) COL_B10_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) priv->col_shift[11] = (((addrmap[4] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) (((addrmap[4] >> 8) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) COL_B11_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) priv->col_shift[11] = ((addrmap[4] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) ((addrmap[4] & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) COL_B10_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) priv->col_shift[13] = (((addrmap[4] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) (((addrmap[4] >> 8) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) COL_B11_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) } else if (width == DDRCTL_EWDTH_32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (memtype & MEM_TYPE_LPDDR3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) priv->col_shift[10] = (((addrmap[3] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) COL_B9_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) priv->col_shift[11] = ((addrmap[4] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) ((addrmap[4] & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) COL_B10_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) priv->col_shift[11] = (((addrmap[3] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) COL_B9_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) priv->col_shift[13] = ((addrmap[4] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ((addrmap[4] & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) COL_B10_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (memtype & MEM_TYPE_LPDDR3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) priv->col_shift[10] = (((addrmap[3] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) (((addrmap[3] >> 16) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) COL_B8_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) priv->col_shift[11] = (((addrmap[3] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) COL_B9_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) priv->col_shift[13] = ((addrmap[4] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) ((addrmap[4] & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) COL_B10_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) priv->col_shift[11] = (((addrmap[3] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) (((addrmap[3] >> 16) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) COL_B8_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) priv->col_shift[13] = (((addrmap[3] >> 24) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) COL_B9_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) for (index = 9; index > width; index--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) priv->col_shift[index] = priv->col_shift[index - width];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) priv->col_shift[index - width] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) static void setup_bank_address_map(struct synps_edac_priv *priv, u32 *addrmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) priv->bank_shift[0] = (addrmap[1] & BANK_MAX_VAL_MASK) + BANK_B0_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) priv->bank_shift[1] = ((addrmap[1] >> 8) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) BANK_MAX_VAL_MASK) + BANK_B1_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) priv->bank_shift[2] = (((addrmap[1] >> 16) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) BANK_MAX_VAL_MASK) == BANK_MAX_VAL_MASK) ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) (((addrmap[1] >> 16) & BANK_MAX_VAL_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) BANK_B2_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static void setup_bg_address_map(struct synps_edac_priv *priv, u32 *addrmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) priv->bankgrp_shift[0] = (addrmap[8] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) BANKGRP_MAX_VAL_MASK) + BANKGRP_B0_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) priv->bankgrp_shift[1] = (((addrmap[8] >> 8) & BANKGRP_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) BANKGRP_MAX_VAL_MASK) ? 0 : (((addrmap[8] >> 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) & BANKGRP_MAX_VAL_MASK) + BANKGRP_B1_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static void setup_rank_address_map(struct synps_edac_priv *priv, u32 *addrmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) priv->rank_shift[0] = ((addrmap[0] & RANK_MAX_VAL_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) RANK_MAX_VAL_MASK) ? 0 : ((addrmap[0] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) RANK_MAX_VAL_MASK) + RANK_B0_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * setup_address_map - Set Address Map by querying ADDRMAP registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * @priv: DDR memory controller private instance data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * Set Address Map by querying ADDRMAP registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) * Return: none.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) static void setup_address_map(struct synps_edac_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) u32 addrmap[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) for (index = 0; index < 12; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) u32 addrmap_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) addrmap_offset = ECC_ADDRMAP0_OFFSET + (index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) addrmap[index] = readl(priv->baseaddr + addrmap_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) setup_row_address_map(priv, addrmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) setup_column_address_map(priv, addrmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) setup_bank_address_map(priv, addrmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) setup_bg_address_map(priv, addrmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) setup_rank_address_map(priv, addrmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) #endif /* CONFIG_EDAC_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) * mc_probe - Check controller and bind driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) * @pdev: platform device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) * Probe a specific controller instance for binding with the driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * Return: 0 if the controller instance was successfully bound to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * driver; otherwise, < 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static int mc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) const struct synps_platform_data *p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct edac_mc_layer layers[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) struct synps_edac_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) void __iomem *baseaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) baseaddr = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (IS_ERR(baseaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return PTR_ERR(baseaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) p_data = of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (!p_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (!p_data->get_ecc_state(baseaddr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) layers[0].size = SYNPS_EDAC_NR_CSROWS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) layers[0].is_virt_csrow = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) layers[1].type = EDAC_MC_LAYER_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) layers[1].size = SYNPS_EDAC_NR_CHANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) layers[1].is_virt_csrow = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) sizeof(struct synps_edac_priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (!mci) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) edac_printk(KERN_ERR, EDAC_MC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) "Failed memory allocation for mc instance\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) priv->baseaddr = baseaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) priv->p_data = p_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) mc_init(mci, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) rc = setup_irq(mci, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) goto free_edac_mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) rc = edac_mc_add_mc(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) edac_printk(KERN_ERR, EDAC_MC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) "Failed to register with EDAC core\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) goto free_edac_mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (priv->p_data->quirks & DDR_ECC_DATA_POISON_SUPPORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (edac_create_sysfs_attributes(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) edac_printk(KERN_ERR, EDAC_MC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) "Failed to create sysfs entries\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) goto free_edac_mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) setup_address_map(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * Start capturing the correctable and uncorrectable errors. A write of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * 0 starts the counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (!(priv->p_data->quirks & DDR_ECC_INTR_SUPPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) writel(0x0, baseaddr + ECC_CTRL_OFST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) free_edac_mc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) * mc_remove - Unbind driver from controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) * @pdev: Platform device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * Return: Unconditionally 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) static int mc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) struct mem_ctl_info *mci = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) struct synps_edac_priv *priv = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) disable_intr(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (priv->p_data->quirks & DDR_ECC_DATA_POISON_SUPPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) edac_remove_sysfs_attributes(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) edac_mc_del_mc(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) static struct platform_driver synps_edac_mc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) .name = "synopsys-edac",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) .of_match_table = synps_edac_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) .probe = mc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) .remove = mc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) module_platform_driver(synps_edac_mc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) MODULE_AUTHOR("Xilinx Inc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) MODULE_DESCRIPTION("Synopsys DDR ECC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) MODULE_LICENSE("GPL v2");