Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:42

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsAArch64XilinxZynqMP
0007  *
0008  * @brief This source file contains the implementation of DDR ECC support.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
0013  * Written by Kinsey Moore <kinsey.moore@oarcorp.com>
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #include <bsp.h>
0038 #include <bsp/ecc_priv.h>
0039 #include <bsp/irq.h>
0040 #include <bsp/utility.h>
0041 #include <rtems/rtems/intr.h>
0042 
0043 static uintptr_t ddrc_base = 0xFD070000;
0044 
0045 /*
0046  * The upper value expressable by the bits in a field is sometimes used to
0047  * indicate different things
0048  */
0049 #define DDRC_ADDRMAP_4BIT_SPECIAL 15
0050 #define DDRC_ADDRMAP_5BIT_SPECIAL 31
0051 
0052 #define DDRC_MSTR_OFFSET 0x0
0053 #define DDRC_MSTR_BURST_RDWR(val) BSP_FLD32(val, 16, 19)
0054 #define DDRC_MSTR_BURST_RDWR_GET(reg) BSP_FLD32GET(reg, 16, 19)
0055 #define DDRC_MSTR_BURST_RDWR_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0056 #define DDRC_MSTR_BURST_RDWR_4 0x2
0057 #define DDRC_MSTR_BURST_RDWR_8 0x4
0058 #define DDRC_MSTR_BURST_RDWR_16 0x8
0059 #define DDRC_MSTR_DATA_BUS_WIDTH(val) BSP_FLD32(val, 12, 13)
0060 #define DDRC_MSTR_DATA_BUS_WIDTH_GET(reg) BSP_FLD32GET(reg, 12, 13)
0061 #define DDRC_MSTR_DATA_BUS_WIDTH_SET(reg, val) BSP_FLD32SET(reg, val, 12, 13)
0062 #define DDRC_MSTR_DATA_BUS_WIDTH_FULL 0x0
0063 #define DDRC_MSTR_DATA_BUS_WIDTH_HALF 0x1
0064 #define DDRC_MSTR_DATA_BUS_WIDTH_QUARTER 0x2
0065 #define DDRC_MSTR_LPDDR4 BSP_BIT32(5)
0066 #define DDRC_MSTR_DDR4 BSP_BIT32(4)
0067 #define DDRC_MSTR_LPDDR3 BSP_BIT32(3)
0068 #define DDRC_MSTR_DDR3 BSP_BIT32(0)
0069 
0070 /* Address map definitions, DDR4 variant with full bus width expected */
0071 #define DDRC_ADDRMAP0_OFFSET 0x200
0072 #define DDRC_ADDRMAP0_RANK_B0_BASE 6
0073 #define DDRC_ADDRMAP0_RANK_B0_TARGET_BIT(bw, lp3) 0
0074 #define DDRC_ADDRMAP0_RANK_B0_TARGET rank
0075 #define DDRC_ADDRMAP0_RANK_B0_SPECIAL DDRC_ADDRMAP_5BIT_SPECIAL
0076 #define DDRC_ADDRMAP0_RANK_B0(val) BSP_FLD32(val, 0, 4)
0077 #define DDRC_ADDRMAP0_RANK_B0_GET(reg) BSP_FLD32GET(reg, 0, 4)
0078 #define DDRC_ADDRMAP0_RANK_B0_SET(reg, val) BSP_FLD32SET(reg, val, 0, 4)
0079 
0080 #define DDRC_ADDRMAP1_OFFSET 0x204
0081 #define DDRC_ADDRMAP1_BANK_B2_BASE 4
0082 #define DDRC_ADDRMAP1_BANK_B2_TARGET_BIT(bw, lp3) 2
0083 #define DDRC_ADDRMAP1_BANK_B2_TARGET bank
0084 #define DDRC_ADDRMAP1_BANK_B2_SPECIAL DDRC_ADDRMAP_5BIT_SPECIAL
0085 #define DDRC_ADDRMAP1_BANK_B2(val) BSP_FLD32(val, 16, 20)
0086 #define DDRC_ADDRMAP1_BANK_B2_GET(reg) BSP_FLD32GET(reg, 16, 20)
0087 #define DDRC_ADDRMAP1_BANK_B2_SET(reg, val) BSP_FLD32SET(reg, val, 16, 20)
0088 #define DDRC_ADDRMAP1_BANK_B1_BASE 3
0089 #define DDRC_ADDRMAP1_BANK_B1_TARGET_BIT(bw, lp3) 1
0090 #define DDRC_ADDRMAP1_BANK_B1_TARGET bank
0091 #define DDRC_ADDRMAP1_BANK_B1_SPECIAL DDRC_ADDRMAP_5BIT_SPECIAL
0092 #define DDRC_ADDRMAP1_BANK_B1(val) BSP_FLD32(val, 8, 12)
0093 #define DDRC_ADDRMAP1_BANK_B1_GET(reg) BSP_FLD32GET(reg, 8, 12)
0094 #define DDRC_ADDRMAP1_BANK_B1_SET(reg, val) BSP_FLD32SET(reg, val, 8, 12)
0095 #define DDRC_ADDRMAP1_BANK_B0_BASE 2
0096 #define DDRC_ADDRMAP1_BANK_B0_TARGET_BIT(bw, lp3) 0
0097 #define DDRC_ADDRMAP1_BANK_B0_TARGET bank
0098 #define DDRC_ADDRMAP1_BANK_B0_SPECIAL DDRC_ADDRMAP_5BIT_SPECIAL
0099 #define DDRC_ADDRMAP1_BANK_B0(val) BSP_FLD32(val, 0, 4)
0100 #define DDRC_ADDRMAP1_BANK_B0_GET(reg) BSP_FLD32GET(reg, 0, 4)
0101 #define DDRC_ADDRMAP1_BANK_B0_SET(reg, val) BSP_FLD32SET(reg, val, 0, 4)
0102 
0103 #define DDRC_ADDRMAP2_OFFSET 0x208
0104 #define DDRC_ADDRMAP2_COL_B5_BASE 5
0105 #define DDRC_ADDRMAP2_COL_B5_TARGET_BIT(bw, lp3) \
0106   ((bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) ? \
0107     5 : ((bw == DDRC_MSTR_DATA_BUS_WIDTH_HALF) ? 6 : 7))
0108 #define DDRC_ADDRMAP2_COL_B5_TARGET column
0109 #define DDRC_ADDRMAP2_COL_B5_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0110 #define DDRC_ADDRMAP2_COL_B5(val) BSP_FLD32(val, 24, 27)
0111 #define DDRC_ADDRMAP2_COL_B5_GET(reg) BSP_FLD32GET(reg, 24, 27)
0112 #define DDRC_ADDRMAP2_COL_B5_SET(reg, val) BSP_FLD32SET(reg, val, 24, 27)
0113 #define DDRC_ADDRMAP2_COL_B4_BASE 4
0114 #define DDRC_ADDRMAP2_COL_B4_TARGET_BIT(bw, lp3) \
0115   ((bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) ? \
0116     4 : ((bw == DDRC_MSTR_DATA_BUS_WIDTH_HALF) ? 5 : 6))
0117 #define DDRC_ADDRMAP2_COL_B4_TARGET column
0118 #define DDRC_ADDRMAP2_COL_B4_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0119 #define DDRC_ADDRMAP2_COL_B4(val) BSP_FLD32(val, 16, 19)
0120 #define DDRC_ADDRMAP2_COL_B4_GET(reg) BSP_FLD32GET(reg, 16, 19)
0121 #define DDRC_ADDRMAP2_COL_B4_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0122 #define DDRC_ADDRMAP2_COL_B3_BASE 3
0123 #define DDRC_ADDRMAP2_COL_B3_TARGET_BIT(bw, lp3) \
0124   ((bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) ? \
0125     3 : ((bw == DDRC_MSTR_DATA_BUS_WIDTH_HALF) ? 4 : 5 ))
0126 #define DDRC_ADDRMAP2_COL_B3_TARGET column
0127 #define DDRC_ADDRMAP2_COL_B3_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0128 #define DDRC_ADDRMAP2_COL_B3(val) BSP_FLD32(val, 8, 11)
0129 #define DDRC_ADDRMAP2_COL_B3_GET(reg) BSP_FLD32GET(reg, 8, 11)
0130 #define DDRC_ADDRMAP2_COL_B3_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0131 #define DDRC_ADDRMAP2_COL_B2_BASE 2
0132 #define DDRC_ADDRMAP2_COL_B2_TARGET_BIT(bw, lp3) \
0133   ((bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) ? \
0134     2 : ((bw == DDRC_MSTR_DATA_BUS_WIDTH_HALF) ? 3 : 4))
0135 #define DDRC_ADDRMAP2_COL_B2_TARGET column
0136 #define DDRC_ADDRMAP2_COL_B2_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0137 #define DDRC_ADDRMAP2_COL_B2(val) BSP_FLD32(val, 0, 3)
0138 #define DDRC_ADDRMAP2_COL_B2_GET(reg) BSP_FLD32GET(reg, 0, 3)
0139 #define DDRC_ADDRMAP2_COL_B2_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0140 
0141 #define DDRC_ADDRMAP3_OFFSET 0x20c
0142 #define DDRC_ADDRMAP3_COL_B9_BASE 9
0143 static uint32_t map3_col_b9_target_bit(uint32_t bw, bool lp3)
0144 {
0145   if (bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) {
0146     return 9;
0147   }
0148 
0149   if (bw == DDRC_MSTR_DATA_BUS_WIDTH_QUARTER) {
0150     return 13;
0151   }
0152 
0153   if (lp3) {
0154     return 10;
0155   }
0156 
0157   return 11;
0158 }
0159 #define DDRC_ADDRMAP3_COL_B9_TARGET_BIT(bw, lp3) \
0160   map3_col_b9_target_bit(bw, lp3)
0161 #define DDRC_ADDRMAP3_COL_B9_TARGET column
0162 #define DDRC_ADDRMAP3_COL_B9_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0163 #define DDRC_ADDRMAP3_COL_B9(val) BSP_FLD32(val, 24, 27)
0164 #define DDRC_ADDRMAP3_COL_B9_GET(reg) BSP_FLD32GET(reg, 24, 27)
0165 #define DDRC_ADDRMAP3_COL_B9_SET(reg, val) BSP_FLD32SET(reg, val, 24, 27)
0166 #define DDRC_ADDRMAP3_COL_B8_BASE 8
0167 #define DDRC_ADDRMAP3_COL_B8_TARGET_BIT(bw, lp3) \
0168   ((bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) ? \
0169     8 : ((bw == DDRC_MSTR_DATA_BUS_WIDTH_HALF) ? 9 : 11))
0170 #define DDRC_ADDRMAP3_COL_B8_TARGET column
0171 #define DDRC_ADDRMAP3_COL_B8_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0172 #define DDRC_ADDRMAP3_COL_B8(val) BSP_FLD32(val, 16, 19)
0173 #define DDRC_ADDRMAP3_COL_B8_GET(reg) BSP_FLD32GET(reg, 16, 19)
0174 #define DDRC_ADDRMAP3_COL_B8_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0175 #define DDRC_ADDRMAP3_COL_B7_BASE 7
0176 #define DDRC_ADDRMAP3_COL_B7_TARGET_BIT(bw, lp3) \
0177   ((bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) ? \
0178     7 : ((bw == DDRC_MSTR_DATA_BUS_WIDTH_HALF) ? 8 : 9))
0179 #define DDRC_ADDRMAP3_COL_B7_TARGET column
0180 #define DDRC_ADDRMAP3_COL_B7_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0181 #define DDRC_ADDRMAP3_COL_B7(val) BSP_FLD32(val, 8, 11)
0182 #define DDRC_ADDRMAP3_COL_B7_GET(reg) BSP_FLD32GET(reg, 8, 11)
0183 #define DDRC_ADDRMAP3_COL_B7_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0184 #define DDRC_ADDRMAP3_COL_B6_BASE 6
0185 #define DDRC_ADDRMAP3_COL_B6_TARGET_BIT(bw, lp3) \
0186   ((bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) ? \
0187     6 : ((bw == DDRC_MSTR_DATA_BUS_WIDTH_HALF) ? 7 : 8))
0188 #define DDRC_ADDRMAP3_COL_B6_TARGET column
0189 #define DDRC_ADDRMAP3_COL_B6_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0190 #define DDRC_ADDRMAP3_COL_B6(val) BSP_FLD32(val, 0, 3)
0191 #define DDRC_ADDRMAP3_COL_B6_GET(reg) BSP_FLD32GET(reg, 0, 3)
0192 #define DDRC_ADDRMAP3_COL_B6_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0193 
0194 #define DDRC_ADDRMAP4_OFFSET 0x210
0195 #define DDRC_ADDRMAP4_COL_B11_BASE 11
0196 #define DDRC_ADDRMAP4_COL_B11_TARGET_BIT(bw, lp3) \
0197   (lp3?11:13)
0198 #define DDRC_ADDRMAP4_COL_B11_TARGET column
0199 #define DDRC_ADDRMAP4_COL_B11_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0200 #define DDRC_ADDRMAP4_COL_B11(val) BSP_FLD32(val, 8, 11)
0201 #define DDRC_ADDRMAP4_COL_B11_GET(reg) BSP_FLD32GET(reg, 8, 11)
0202 #define DDRC_ADDRMAP4_COL_B11_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0203 #define DDRC_ADDRMAP4_COL_B10_BASE 10
0204 static uint32_t map4_col_b10_target_bit(uint32_t bw, bool lp3)
0205 {
0206   if (bw == DDRC_MSTR_DATA_BUS_WIDTH_FULL) {
0207     if (lp3) {
0208       return 10;
0209     }
0210     return 11;
0211   }
0212 
0213   /* QUARTER bus mode not valid */
0214   if (lp3) {
0215     return 11;
0216   }
0217 
0218   return 13;
0219 }
0220 #define DDRC_ADDRMAP4_COL_B10_TARGET_BIT(bw, lp3) \
0221   map4_col_b10_target_bit(bw, lp3)
0222 #define DDRC_ADDRMAP4_COL_B10_TARGET column
0223 #define DDRC_ADDRMAP4_COL_B10_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0224 #define DDRC_ADDRMAP4_COL_B10(val) BSP_FLD32(val, 0, 3)
0225 #define DDRC_ADDRMAP4_COL_B10_GET(reg) BSP_FLD32GET(reg, 0, 3)
0226 #define DDRC_ADDRMAP4_COL_B10_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0227 
0228 #define DDRC_ADDRMAP5_OFFSET 0x214
0229 #define DDRC_ADDRMAP5_ROW_B11_BASE 17
0230 #define DDRC_ADDRMAP5_ROW_B11_TARGET_BIT(bw, lp3) 11
0231 #define DDRC_ADDRMAP5_ROW_B11_TARGET row
0232 #define DDRC_ADDRMAP5_ROW_B11_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0233 #define DDRC_ADDRMAP5_ROW_B11(val) BSP_FLD32(val, 24, 27)
0234 #define DDRC_ADDRMAP5_ROW_B11_GET(reg) BSP_FLD32GET(reg, 24, 27)
0235 #define DDRC_ADDRMAP5_ROW_B11_SET(reg, val) BSP_FLD32SET(reg, val, 24, 27)
0236 /* This gets mapped into ADDRMAP[9,10,11] */
0237 #define DDRC_ADDRMAP5_ROW_B2_10(val) BSP_FLD32(val, 16, 19)
0238 #define DDRC_ADDRMAP5_ROW_B2_10_GET(reg) BSP_FLD32GET(reg, 16, 19)
0239 #define DDRC_ADDRMAP5_ROW_B2_10_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0240 #define DDRC_ADDRMAP5_ROW_B1_BASE 7
0241 #define DDRC_ADDRMAP5_ROW_B1_TARGET_BIT(bw, lp3) 1
0242 #define DDRC_ADDRMAP5_ROW_B1_TARGET row
0243 #define DDRC_ADDRMAP5_ROW_B1_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0244 #define DDRC_ADDRMAP5_ROW_B1(val) BSP_FLD32(val, 8, 11)
0245 #define DDRC_ADDRMAP5_ROW_B1_GET(reg) BSP_FLD32GET(reg, 8, 11)
0246 #define DDRC_ADDRMAP5_ROW_B1_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0247 #define DDRC_ADDRMAP5_ROW_B0_BASE 6
0248 #define DDRC_ADDRMAP5_ROW_B0_TARGET_BIT(bw, lp3) 0
0249 #define DDRC_ADDRMAP5_ROW_B0_TARGET row
0250 #define DDRC_ADDRMAP5_ROW_B0_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0251 #define DDRC_ADDRMAP5_ROW_B0(val) BSP_FLD32(val, 0, 3)
0252 #define DDRC_ADDRMAP5_ROW_B0_GET(reg) BSP_FLD32GET(reg, 0, 3)
0253 #define DDRC_ADDRMAP5_ROW_B0_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0254 
0255 #define DDRC_ADDRMAP6_OFFSET 0x218
0256 #define DDRC_ADDRMAP6_LPDDR3_6_12 BSP_BIT(bw, lp3)32(31)
0257 #define DDRC_ADDRMAP6_ROW_B15_BASE 21
0258 #define DDRC_ADDRMAP6_ROW_B15_TARGET_BIT(bw, lp3) 15
0259 #define DDRC_ADDRMAP6_ROW_B15_TARGET row
0260 #define DDRC_ADDRMAP6_ROW_B15_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0261 #define DDRC_ADDRMAP6_ROW_B15(val) BSP_FLD32(val, 24, 27)
0262 #define DDRC_ADDRMAP6_ROW_B15_GET(reg) BSP_FLD32GET(reg, 24, 27)
0263 #define DDRC_ADDRMAP6_ROW_B15_SET(reg, val) BSP_FLD32SET(reg, val, 24, 27)
0264 #define DDRC_ADDRMAP6_ROW_B14_BASE 20
0265 #define DDRC_ADDRMAP6_ROW_B14_TARGET_BIT(bw, lp3) 14
0266 #define DDRC_ADDRMAP6_ROW_B14_TARGET row
0267 #define DDRC_ADDRMAP6_ROW_B14_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0268 #define DDRC_ADDRMAP6_ROW_B14(val) BSP_FLD32(val, 16, 19)
0269 #define DDRC_ADDRMAP6_ROW_B14_GET(reg) BSP_FLD32GET(reg, 16, 19)
0270 #define DDRC_ADDRMAP6_ROW_B14_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0271 #define DDRC_ADDRMAP6_ROW_B13_BASE 19
0272 #define DDRC_ADDRMAP6_ROW_B13_TARGET_BIT(bw, lp3) 13
0273 #define DDRC_ADDRMAP6_ROW_B13_TARGET row
0274 #define DDRC_ADDRMAP6_ROW_B13_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0275 #define DDRC_ADDRMAP6_ROW_B13(val) BSP_FLD32(val, 8, 11)
0276 #define DDRC_ADDRMAP6_ROW_B13_GET(reg) BSP_FLD32GET(reg, 8, 11)
0277 #define DDRC_ADDRMAP6_ROW_B13_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0278 #define DDRC_ADDRMAP6_ROW_B12_BASE 18
0279 #define DDRC_ADDRMAP6_ROW_B12_TARGET_BIT(bw, lp3) 12
0280 #define DDRC_ADDRMAP6_ROW_B12_TARGET row
0281 #define DDRC_ADDRMAP6_ROW_B12_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0282 #define DDRC_ADDRMAP6_ROW_B12(val) BSP_FLD32(val, 0, 3)
0283 #define DDRC_ADDRMAP6_ROW_B12_GET(reg) BSP_FLD32GET(reg, 0, 3)
0284 #define DDRC_ADDRMAP6_ROW_B12_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0285 
0286 #define DDRC_ADDRMAP7_OFFSET 0x21c
0287 #define DDRC_ADDRMAP7_ROW_B17_BASE 23
0288 #define DDRC_ADDRMAP7_ROW_B17_TARGET_BIT(bw, lp3) 17
0289 #define DDRC_ADDRMAP7_ROW_B17_TARGET row
0290 #define DDRC_ADDRMAP7_ROW_B17_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0291 #define DDRC_ADDRMAP7_ROW_B17(val) BSP_FLD32(val, 8, 11)
0292 #define DDRC_ADDRMAP7_ROW_B17_GET(reg) BSP_FLD32GET(reg, 8, 11)
0293 #define DDRC_ADDRMAP7_ROW_B17_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0294 #define DDRC_ADDRMAP7_ROW_B16_BASE 22
0295 #define DDRC_ADDRMAP7_ROW_B16_TARGET_BIT(bw, lp3) 16
0296 #define DDRC_ADDRMAP7_ROW_B16_TARGET row
0297 #define DDRC_ADDRMAP7_ROW_B16_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0298 #define DDRC_ADDRMAP7_ROW_B16(val) BSP_FLD32(val, 0, 3)
0299 #define DDRC_ADDRMAP7_ROW_B16_GET(reg) BSP_FLD32GET(reg, 0, 3)
0300 #define DDRC_ADDRMAP7_ROW_B16_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0301 
0302 #define DDRC_ADDRMAP8_OFFSET 0x220
0303 #define DDRC_ADDRMAP8_BG_B1_BASE 3
0304 #define DDRC_ADDRMAP8_BG_B1_TARGET_BIT(bw, lp3) 1
0305 #define DDRC_ADDRMAP8_BG_B1_TARGET bank_group
0306 #define DDRC_ADDRMAP8_BG_B1_SPECIAL DDRC_ADDRMAP_5BIT_SPECIAL
0307 #define DDRC_ADDRMAP8_BG_B1(val) BSP_FLD32(val, 8, 12)
0308 #define DDRC_ADDRMAP8_BG_B1_GET(reg) BSP_FLD32GET(reg, 8, 12)
0309 #define DDRC_ADDRMAP8_BG_B1_SET(reg, val) BSP_FLD32SET(reg, val, 8, 12)
0310 #define DDRC_ADDRMAP8_BG_B0_BASE 2
0311 #define DDRC_ADDRMAP8_BG_B0_TARGET_BIT(bw, lp3) 0
0312 #define DDRC_ADDRMAP8_BG_B0_TARGET bank_group
0313 #define DDRC_ADDRMAP8_BG_B0_SPECIAL DDRC_ADDRMAP_5BIT_SPECIAL
0314 #define DDRC_ADDRMAP8_BG_B0(val) BSP_FLD32(val, 0, 4)
0315 #define DDRC_ADDRMAP8_BG_B0_GET(reg) BSP_FLD32GET(reg, 0, 4)
0316 #define DDRC_ADDRMAP8_BG_B0_SET(reg, val) BSP_FLD32SET(reg, val, 0, 4)
0317 
0318 #define DDRC_ADDRMAP9_OFFSET 0x224
0319 #define DDRC_ADDRMAP9_ROW_B5_BASE 11
0320 #define DDRC_ADDRMAP9_ROW_B5_TARGET_BIT(bw, lp3) 5
0321 #define DDRC_ADDRMAP9_ROW_B5_TARGET row
0322 #define DDRC_ADDRMAP9_ROW_B5_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0323 #define DDRC_ADDRMAP9_ROW_B5(val) BSP_FLD32(val, 24, 27)
0324 #define DDRC_ADDRMAP9_ROW_B5_GET(reg) BSP_FLD32GET(reg, 24, 27)
0325 #define DDRC_ADDRMAP9_ROW_B5_SET(reg, val) BSP_FLD32SET(reg, val, 24, 27)
0326 #define DDRC_ADDRMAP9_ROW_B4_BASE 10
0327 #define DDRC_ADDRMAP9_ROW_B4_TARGET_BIT(bw, lp3) 4
0328 #define DDRC_ADDRMAP9_ROW_B4_TARGET row
0329 #define DDRC_ADDRMAP9_ROW_B4_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0330 #define DDRC_ADDRMAP9_ROW_B4(val) BSP_FLD32(val, 16, 19)
0331 #define DDRC_ADDRMAP9_ROW_B4_GET(reg) BSP_FLD32GET(reg, 16, 19)
0332 #define DDRC_ADDRMAP9_ROW_B4_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0333 #define DDRC_ADDRMAP9_ROW_B3_BASE 9
0334 #define DDRC_ADDRMAP9_ROW_B3_TARGET_BIT(bw, lp3) 3
0335 #define DDRC_ADDRMAP9_ROW_B3_TARGET row
0336 #define DDRC_ADDRMAP9_ROW_B3_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0337 #define DDRC_ADDRMAP9_ROW_B3(val) BSP_FLD32(val, 8, 11)
0338 #define DDRC_ADDRMAP9_ROW_B3_GET(reg) BSP_FLD32GET(reg, 8, 11)
0339 #define DDRC_ADDRMAP9_ROW_B3_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0340 #define DDRC_ADDRMAP9_ROW_B2_BASE 8
0341 #define DDRC_ADDRMAP9_ROW_B2_TARGET_BIT(bw, lp3) 2
0342 #define DDRC_ADDRMAP9_ROW_B2_TARGET row
0343 #define DDRC_ADDRMAP9_ROW_B2_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0344 #define DDRC_ADDRMAP9_ROW_B2(val) BSP_FLD32(val, 0, 3)
0345 #define DDRC_ADDRMAP9_ROW_B2_GET(reg) BSP_FLD32GET(reg, 0, 3)
0346 #define DDRC_ADDRMAP9_ROW_B2_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0347 
0348 #define DDRC_ADDRMAP10_OFFSET 0x228
0349 #define DDRC_ADDRMAP10_ROW_B9_BASE 15
0350 #define DDRC_ADDRMAP10_ROW_B9_TARGET_BIT(bw, lp3) 9
0351 #define DDRC_ADDRMAP10_ROW_B9_TARGET row
0352 #define DDRC_ADDRMAP10_ROW_B9_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0353 #define DDRC_ADDRMAP10_ROW_B9(val) BSP_FLD32(val, 24, 27)
0354 #define DDRC_ADDRMAP10_ROW_B9_GET(reg) BSP_FLD32GET(reg, 24, 27)
0355 #define DDRC_ADDRMAP10_ROW_B9_SET(reg, val) BSP_FLD32SET(reg, val, 24, 27)
0356 #define DDRC_ADDRMAP10_ROW_B8_BASE 14
0357 #define DDRC_ADDRMAP10_ROW_B8_TARGET_BIT(bw, lp3) 8
0358 #define DDRC_ADDRMAP10_ROW_B8_TARGET row
0359 #define DDRC_ADDRMAP10_ROW_B8_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0360 #define DDRC_ADDRMAP10_ROW_B8(val) BSP_FLD32(val, 16, 19)
0361 #define DDRC_ADDRMAP10_ROW_B8_GET(reg) BSP_FLD32GET(reg, 16, 19)
0362 #define DDRC_ADDRMAP10_ROW_B8_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0363 #define DDRC_ADDRMAP10_ROW_B7_BASE 13
0364 #define DDRC_ADDRMAP10_ROW_B7_TARGET_BIT(bw, lp3) 7
0365 #define DDRC_ADDRMAP10_ROW_B7_TARGET row
0366 #define DDRC_ADDRMAP10_ROW_B7_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0367 #define DDRC_ADDRMAP10_ROW_B7(val) BSP_FLD32(val, 8, 11)
0368 #define DDRC_ADDRMAP10_ROW_B7_GET(reg) BSP_FLD32GET(reg, 8, 11)
0369 #define DDRC_ADDRMAP10_ROW_B7_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0370 #define DDRC_ADDRMAP10_ROW_B6_BASE 12
0371 #define DDRC_ADDRMAP10_ROW_B6_TARGET_BIT(bw, lp3) 6
0372 #define DDRC_ADDRMAP10_ROW_B6_TARGET row
0373 #define DDRC_ADDRMAP10_ROW_B6_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0374 #define DDRC_ADDRMAP10_ROW_B6(val) BSP_FLD32(val, 0, 3)
0375 #define DDRC_ADDRMAP10_ROW_B6_GET(reg) BSP_FLD32GET(reg, 0, 3)
0376 #define DDRC_ADDRMAP10_ROW_B6_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0377 
0378 #define DDRC_ADDRMAP11_OFFSET 0x22c
0379 #define DDRC_ADDRMAP11_ROW_B10_BASE 16
0380 #define DDRC_ADDRMAP11_ROW_B10_TARGET_BIT(bw, lp3) 10
0381 #define DDRC_ADDRMAP11_ROW_B10_TARGET row
0382 #define DDRC_ADDRMAP11_ROW_B10_SPECIAL DDRC_ADDRMAP_4BIT_SPECIAL
0383 #define DDRC_ADDRMAP11_ROW_B10(val) BSP_FLD32(val, 0, 3)
0384 #define DDRC_ADDRMAP11_ROW_B10_GET(reg) BSP_FLD32GET(reg, 0, 3)
0385 #define DDRC_ADDRMAP11_ROW_B10_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
0386 
0387 #define DDRC_ECCPOISONADDR0_OFFSET 0xB8
0388 #define DDRC_ECCPOISONADDR0_RANK BSP_BIT32(24)
0389 #define DDRC_ECCPOISONADDR0_COL(val) BSP_FLD32(val, 0, 11)
0390 #define DDRC_ECCPOISONADDR0_COL_GET(reg) BSP_FLD32GET(reg, 0, 11)
0391 #define DDRC_ECCPOISONADDR0_COL_SET(reg, val) BSP_FLD32SET(reg, val, 0, 11)
0392 
0393 #define DDRC_ECCPOISONADDR1_OFFSET 0xBC
0394 #define DDRC_ECCPOISONADDR1_BG(val) BSP_FLD32(val, 28, 29)
0395 #define DDRC_ECCPOISONADDR1_BG_GET(reg) BSP_FLD32GET(reg, 28, 29)
0396 #define DDRC_ECCPOISONADDR1_BG_SET(reg, val) BSP_FLD32SET(reg, val, 28, 29)
0397 #define DDRC_ECCPOISONADDR1_BANK(val) BSP_FLD32(val, 24, 26)
0398 #define DDRC_ECCPOISONADDR1_BANK_GET(reg) BSP_FLD32GET(reg, 24, 26)
0399 #define DDRC_ECCPOISONADDR1_BANK_SET(reg, val) BSP_FLD32SET(reg, val, 24, 26)
0400 #define DDRC_ECCPOISONADDR1_ROW(val) BSP_FLD32(val, 0, 17)
0401 #define DDRC_ECCPOISONADDR1_ROW_GET(reg) BSP_FLD32GET(reg, 0, 17)
0402 #define DDRC_ECCPOISONADDR1_ROW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 17)
0403 
0404 static void homogenize_row(
0405   uint32_t *addrmap5,
0406   uint32_t *addrmap9,
0407   uint32_t *addrmap10,
0408   uint32_t *addrmap11
0409 )
0410 {
0411   uint32_t b2_10 = DDRC_ADDRMAP5_ROW_B2_10_GET(*addrmap5);
0412   if (b2_10 == DDRC_ADDRMAP_4BIT_SPECIAL) {
0413     /* ADDRMAP[9,10,11] already define row[2:10] correctly */
0414     return;
0415   }
0416 
0417   /* Translate b2_10 to ADDRMAP[9,10,11] to simplify future code */
0418   *addrmap9 = DDRC_ADDRMAP9_ROW_B5_SET(*addrmap9, b2_10);
0419   *addrmap9 = DDRC_ADDRMAP9_ROW_B4_SET(*addrmap9, b2_10);
0420   *addrmap9 = DDRC_ADDRMAP9_ROW_B3_SET(*addrmap9, b2_10);
0421   *addrmap9 = DDRC_ADDRMAP9_ROW_B2_SET(*addrmap9, b2_10);
0422 
0423   *addrmap10 = DDRC_ADDRMAP10_ROW_B9_SET(*addrmap10, b2_10);
0424   *addrmap10 = DDRC_ADDRMAP10_ROW_B8_SET(*addrmap10, b2_10);
0425   *addrmap10 = DDRC_ADDRMAP10_ROW_B7_SET(*addrmap10, b2_10);
0426   *addrmap10 = DDRC_ADDRMAP10_ROW_B6_SET(*addrmap10, b2_10);
0427 
0428   *addrmap11 = DDRC_ADDRMAP11_ROW_B10_SET(*addrmap11, b2_10);
0429 }
0430 
0431 #define DDRC_READ(offset) (*(uint32_t *)(ddrc_base + offset))
0432 
0433 #define DDRC_MAP_BIT(value, source, target) ((value >> source) & 0x1) << target
0434 
0435 #define DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, BIT_ID, info, addrmap) \
0436 ({ \
0437   uint32_t mapbit = DDRC_ ## BIT_ID ## _GET(addrmap); \
0438   uint32_t target_bit = DDRC_ ## BIT_ID ## _TARGET_BIT(bus_width, lpddr3); \
0439   if (mapbit != DDRC_ ## BIT_ID ## _SPECIAL) { \
0440     mapbit += DDRC_ ## BIT_ID ## _BASE; \
0441     /* account for AXI -> HIF shift */ \
0442     mapbit += 3; \
0443     info->address |= \
0444       DDRC_MAP_BIT(info-> DDRC_ ## BIT_ID ## _TARGET, target_bit, mapbit); \
0445   } \
0446 })
0447 
0448 /*
0449  * Steps in mapping an address:
0450  * system address -> DDRC -> AXI byte address:
0451  *   disjoint memory regions are mapped into a monolithic block representing
0452  *     total available RAM based on configured offsets
0453  * AXI byte address -> XPI -> HIF word address:
0454  *   word-sized shift of 3 bits for 8 byte (word) alignment
0455  * HIF word address -> DDRC -> SDRAM address:
0456  *   addresses are mapped into SDRAM terms by the flexible address mapper using
0457  *     the ADDRMAP* registers
0458  */
0459 static int compose_address(DDR_Error_Info *info)
0460 {
0461   uint32_t addrmap0 = DDRC_READ(DDRC_ADDRMAP0_OFFSET);
0462   uint32_t addrmap1 = DDRC_READ(DDRC_ADDRMAP1_OFFSET);
0463   uint32_t addrmap2 = DDRC_READ(DDRC_ADDRMAP2_OFFSET);
0464   uint32_t addrmap3 = DDRC_READ(DDRC_ADDRMAP3_OFFSET);
0465   uint32_t addrmap4 = DDRC_READ(DDRC_ADDRMAP4_OFFSET);
0466   uint32_t addrmap5 = DDRC_READ(DDRC_ADDRMAP5_OFFSET);
0467   uint32_t addrmap6 = DDRC_READ(DDRC_ADDRMAP6_OFFSET);
0468   uint32_t addrmap7 = DDRC_READ(DDRC_ADDRMAP7_OFFSET);
0469   uint32_t addrmap8 = DDRC_READ(DDRC_ADDRMAP8_OFFSET);
0470   uint32_t addrmap9 = DDRC_READ(DDRC_ADDRMAP9_OFFSET);
0471   uint32_t addrmap10 = DDRC_READ(DDRC_ADDRMAP10_OFFSET);
0472   uint32_t addrmap11 = DDRC_READ(DDRC_ADDRMAP11_OFFSET);
0473   uint32_t mstr = DDRC_READ(DDRC_MSTR_OFFSET);
0474   uint32_t bus_width = DDRC_MSTR_DATA_BUS_WIDTH_GET(mstr);
0475   bool lpddr3 = mstr & DDRC_MSTR_LPDDR3;
0476 
0477   homogenize_row(&addrmap5, &addrmap9, &addrmap10, &addrmap11);
0478   
0479   /* Clear items that will be written to */
0480   info->address = 0;
0481 
0482   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP0_RANK_B0, info, addrmap0);
0483   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP1_BANK_B2, info, addrmap1);
0484   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP1_BANK_B1, info, addrmap1);
0485   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP1_BANK_B0, info, addrmap1);
0486   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP2_COL_B5, info, addrmap2);
0487   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP2_COL_B4, info, addrmap2);
0488   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP2_COL_B3, info, addrmap2);
0489   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP2_COL_B2, info, addrmap2);
0490   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP3_COL_B9, info, addrmap3);
0491   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP3_COL_B8, info, addrmap3);
0492   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP3_COL_B7, info, addrmap3);
0493   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP3_COL_B6, info, addrmap3);
0494   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP4_COL_B11, info, addrmap4);
0495   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP4_COL_B10, info, addrmap4);
0496   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP5_ROW_B11, info, addrmap5);
0497   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP5_ROW_B1, info, addrmap5);
0498   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP5_ROW_B0, info, addrmap5);
0499   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP6_ROW_B15, info, addrmap6);
0500   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP6_ROW_B14, info, addrmap6);
0501   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP6_ROW_B13, info, addrmap6);
0502   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP6_ROW_B12, info, addrmap6);
0503   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP7_ROW_B17, info, addrmap7);
0504   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP7_ROW_B16, info, addrmap7);
0505   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP8_BG_B1, info, addrmap8);
0506   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP8_BG_B0, info, addrmap8);
0507   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP9_ROW_B5, info, addrmap9);
0508   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP9_ROW_B4, info, addrmap9);
0509   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP9_ROW_B3, info, addrmap9);
0510   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP9_ROW_B2, info, addrmap9);
0511   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP10_ROW_B9, info, addrmap10);
0512   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP10_ROW_B8, info, addrmap10);
0513   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP10_ROW_B7, info, addrmap10);
0514   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP10_ROW_B6, info, addrmap10);
0515   DDRC_CHECK_AND_UNMAP(bus_width, lpddr3, ADDRMAP11_ROW_B10, info, addrmap11);
0516 
0517   /* Column[0:1] are always statically mapped to HIF[0:1] */
0518   info->address |= (info->column & 0x3) << 3;
0519   return 0;
0520 }
0521 
0522 static uintptr_t ddr_qos_ctrl_base = 0xFD090000;
0523 /* DDR QoS CTRL QoS IRQ Status */
0524 #define DDR_QIS_OFFSET 0x200
0525 #define DDR_QIE_OFFSET 0x208
0526 #define DDR_QID_OFFSET 0x20c
0527 #define DDR_QI_UNCRERR BSP_BIT32(2)
0528 #define DDR_QI_CORERR BSP_BIT32(1)
0529 
0530 #define DDRC_ECCSTAT_OFFSET 0x78
0531 #define DDRC_ECCSTAT_UNCR_ERR(val) BSP_FLD32(val, 16, 19)
0532 #define DDRC_ECCSTAT_UNCR_ERR_GET(reg) BSP_FLD32GET(reg, 16, 19)
0533 #define DDRC_ECCSTAT_UNCR_ERR_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
0534 #define DDRC_ECCSTAT_CORR_ERR(val) BSP_FLD32(val, 8, 11)
0535 #define DDRC_ECCSTAT_CORR_ERR_GET(reg) BSP_FLD32GET(reg, 8, 11)
0536 #define DDRC_ECCSTAT_CORR_ERR_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
0537 #define DDRC_ECCSTAT_CORR_BIT(val) BSP_FLD32(val, 0, 6)
0538 #define DDRC_ECCSTAT_CORR_BIT_GET(reg) BSP_FLD32GET(reg, 0, 6)
0539 #define DDRC_ECCSTAT_CORR_BIT_SET(reg, val) BSP_FLD32SET(reg, val, 0, 6)
0540 
0541 /* Correctable and uncorrectable error address registers share encodings */
0542 #define DDRC_ECCCADDR0_OFFSET 0x84
0543 #define DDRC_ECCUADDR0_OFFSET 0xA4
0544 #define DDRC_ECCXADDR0_RANK BSP_BIT32(24)
0545 #define DDRC_ECCXADDR0_ROW(val) BSP_FLD32(val, 0, 17)
0546 #define DDRC_ECCXADDR0_ROW_GET(reg) BSP_FLD32GET(reg, 0, 17)
0547 #define DDRC_ECCXADDR0_ROW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 17)
0548 
0549 #define DDRC_ECCCADDR1_OFFSET 0x88
0550 #define DDRC_ECCUADDR1_OFFSET 0xA8
0551 #define DDRC_ECCXADDR1_BG(val) BSP_FLD32(val, 24, 25)
0552 #define DDRC_ECCXADDR1_BG_GET(reg) BSP_FLD32GET(reg, 24, 25)
0553 #define DDRC_ECCXADDR1_BG_SET(reg, val) BSP_FLD32SET(reg, val, 24, 25)
0554 #define DDRC_ECCXADDR1_BANK(val) BSP_FLD32(val, 16, 18)
0555 #define DDRC_ECCXADDR1_BANK_GET(reg) BSP_FLD32GET(reg, 16, 18)
0556 #define DDRC_ECCXADDR1_BANK_SET(reg, val) BSP_FLD32SET(reg, val, 16, 18)
0557 #define DDRC_ECCXADDR1_COL(val) BSP_FLD32(val, 0, 11)
0558 #define DDRC_ECCXADDR1_COL_GET(reg) BSP_FLD32GET(reg, 0, 11)
0559 #define DDRC_ECCXADDR1_COL_SET(reg, val) BSP_FLD32SET(reg, val, 0, 11)
0560 
0561 static void extract_ddr_info(
0562   DDR_Error_Info *info,
0563   uint32_t addr0_val,
0564   uint32_t addr1_val
0565 )
0566 {
0567   info->rank = (addr0_val & DDRC_ECCXADDR0_RANK) >> 24;
0568   info->bank_group = DDRC_ECCXADDR1_BG_GET(addr1_val);
0569   info->bank = DDRC_ECCXADDR1_BANK_GET(addr1_val);
0570   info->row = DDRC_ECCXADDR0_ROW_GET(addr0_val);
0571   info->column = DDRC_ECCXADDR1_COL_GET(addr1_val);
0572   compose_address(info);
0573 }
0574 
0575 
0576 static void ddr_handler(void *arg)
0577 {
0578   (void) arg;
0579 
0580   volatile uint32_t *qis = (uint32_t *)(ddr_qos_ctrl_base + DDR_QIS_OFFSET);
0581   uint32_t qis_value = *qis;
0582   DDR_Error_Info info;
0583   volatile uint32_t *addr0 = (uint32_t *)(ddrc_base + DDRC_ECCCADDR0_OFFSET);
0584   volatile uint32_t *addr1 = (uint32_t *)(ddrc_base + DDRC_ECCCADDR1_OFFSET);
0585 
0586   /* specific data is captured in DDRC.ECCSTAT[corrected_bit_num] */
0587   if ((qis_value & DDR_QI_CORERR) != 0) {
0588     /* Clear status flag */
0589     *qis = DDR_QI_CORERR;
0590 
0591     info.type = DDR_CORRECTABLE;
0592     extract_ddr_info(&info, *addr0, *addr1);
0593     zynqmp_invoke_ecc_handler(DDR_RAM, &info);
0594   }
0595   if ((qis_value & DDR_QI_UNCRERR) != 0) {
0596     /* Clear status flag */
0597     *qis = DDR_QI_UNCRERR;
0598 
0599     info.type = DDR_UNCORRECTABLE;
0600     extract_ddr_info(&info, *addr0, *addr1);
0601     zynqmp_invoke_ecc_handler(DDR_RAM, &info);
0602   }
0603 }
0604 
0605 static rtems_interrupt_entry zynqmp_ddr_ecc_entry;
0606 
0607 rtems_status_code zynqmp_configure_ddr_ecc( void )
0608 {
0609   volatile uint32_t *qie = (uint32_t *)(ddr_qos_ctrl_base + DDR_QIE_OFFSET);
0610   rtems_status_code sc;
0611 
0612   rtems_interrupt_entry_initialize(
0613     &zynqmp_ddr_ecc_entry,
0614     ddr_handler,
0615     NULL,
0616     "DDR RAM ECC"
0617   );
0618 
0619   sc = rtems_interrupt_entry_install(
0620     ZYNQMP_IRQ_DDR,
0621     RTEMS_INTERRUPT_SHARED,
0622     &zynqmp_ddr_ecc_entry
0623   );
0624 
0625   if (sc != RTEMS_SUCCESSFUL) {
0626     return sc;
0627   }
0628 
0629   /* enable interrupts for ECC in QOS_IRQ_ENABLE */
0630   *qie |= DDR_QI_UNCRERR | DDR_QI_CORERR;
0631   return RTEMS_SUCCESSFUL;
0632 }
0633 
0634 #if RUNNING_FROM_OCM_IS_NOT_CURRENTLY_POSSIBLE
0635 /*
0636  * Injecting DDR ECC faults requires RTEMS to run from OCM since the DDR will be
0637  * partially disabled and re-enabled during the process. RTEMS is too large to
0638  * run out of OCM in its current configuration and doing so would require
0639  * operation without MMU along with other changes to reduce the memory footprint
0640  * to below 256KB. It must be the whole RTEMS executable since stack accesses
0641  * would also present a problem.
0642  */
0643 
0644 #define DDRC_PRINT_MAP(BIT_ID, addrmap) \
0645 ({ \
0646   uint32_t mapbit = DDRC_ ## BIT_ID ## _GET(addrmap); \
0647   if (mapbit != DDRC_ ## BIT_ID ## _SPECIAL) { \
0648     mapbit += DDRC_ ## BIT_ID ## _BASE; \
0649   } \
0650 })
0651 
0652 static void print_addr_maps( void )
0653 {
0654   uint32_t addrmap0 = DDRC_READ(DDRC_ADDRMAP0_OFFSET);
0655   uint32_t addrmap1 = DDRC_READ(DDRC_ADDRMAP1_OFFSET);
0656   uint32_t addrmap2 = DDRC_READ(DDRC_ADDRMAP2_OFFSET);
0657   uint32_t addrmap3 = DDRC_READ(DDRC_ADDRMAP3_OFFSET);
0658   uint32_t addrmap4 = DDRC_READ(DDRC_ADDRMAP4_OFFSET);
0659   uint32_t addrmap5 = DDRC_READ(DDRC_ADDRMAP5_OFFSET);
0660   uint32_t addrmap6 = DDRC_READ(DDRC_ADDRMAP6_OFFSET);
0661   uint32_t addrmap7 = DDRC_READ(DDRC_ADDRMAP7_OFFSET);
0662   uint32_t addrmap8 = DDRC_READ(DDRC_ADDRMAP8_OFFSET);
0663   uint32_t addrmap9 = DDRC_READ(DDRC_ADDRMAP9_OFFSET);
0664   uint32_t addrmap10 = DDRC_READ(DDRC_ADDRMAP10_OFFSET);
0665   uint32_t addrmap11 = DDRC_READ(DDRC_ADDRMAP11_OFFSET);
0666 
0667   homogenize_row(&addrmap5, &addrmap9, &addrmap10, &addrmap11);
0668 
0669   DDRC_PRINT_MAP(ADDRMAP0_RANK_B0, addrmap0);
0670   DDRC_PRINT_MAP(ADDRMAP1_BANK_B2, addrmap1);
0671   DDRC_PRINT_MAP(ADDRMAP1_BANK_B1, addrmap1);
0672   DDRC_PRINT_MAP(ADDRMAP1_BANK_B0, addrmap1);
0673   DDRC_PRINT_MAP(ADDRMAP2_COL_B5, addrmap2);
0674   DDRC_PRINT_MAP(ADDRMAP2_COL_B4, addrmap2);
0675   DDRC_PRINT_MAP(ADDRMAP2_COL_B3, addrmap2);
0676   DDRC_PRINT_MAP(ADDRMAP2_COL_B2, addrmap2);
0677   DDRC_PRINT_MAP(ADDRMAP3_COL_B9, addrmap3);
0678   DDRC_PRINT_MAP(ADDRMAP3_COL_B8, addrmap3);
0679   DDRC_PRINT_MAP(ADDRMAP3_COL_B7, addrmap3);
0680   DDRC_PRINT_MAP(ADDRMAP3_COL_B6, addrmap3);
0681   DDRC_PRINT_MAP(ADDRMAP4_COL_B11, addrmap4);
0682   DDRC_PRINT_MAP(ADDRMAP4_COL_B10, addrmap4);
0683   DDRC_PRINT_MAP(ADDRMAP5_ROW_B11, addrmap5);
0684   DDRC_PRINT_MAP(ADDRMAP5_ROW_B1, addrmap5);
0685   DDRC_PRINT_MAP(ADDRMAP5_ROW_B0, addrmap5);
0686   DDRC_PRINT_MAP(ADDRMAP6_ROW_B15, addrmap6);
0687   DDRC_PRINT_MAP(ADDRMAP6_ROW_B14, addrmap6);
0688   DDRC_PRINT_MAP(ADDRMAP6_ROW_B13, addrmap6);
0689   DDRC_PRINT_MAP(ADDRMAP6_ROW_B12, addrmap6);
0690   DDRC_PRINT_MAP(ADDRMAP7_ROW_B17, addrmap7);
0691   DDRC_PRINT_MAP(ADDRMAP7_ROW_B16, addrmap7);
0692   DDRC_PRINT_MAP(ADDRMAP8_BG_B1, addrmap8);
0693   DDRC_PRINT_MAP(ADDRMAP8_BG_B0, addrmap8);
0694   DDRC_PRINT_MAP(ADDRMAP9_ROW_B5, addrmap9);
0695   DDRC_PRINT_MAP(ADDRMAP9_ROW_B4, addrmap9);
0696   DDRC_PRINT_MAP(ADDRMAP9_ROW_B3, addrmap9);
0697   DDRC_PRINT_MAP(ADDRMAP9_ROW_B2, addrmap9);
0698   DDRC_PRINT_MAP(ADDRMAP10_ROW_B9, addrmap10);
0699   DDRC_PRINT_MAP(ADDRMAP10_ROW_B8, addrmap10);
0700   DDRC_PRINT_MAP(ADDRMAP10_ROW_B7, addrmap10);
0701   DDRC_PRINT_MAP(ADDRMAP10_ROW_B6, addrmap10);
0702   DDRC_PRINT_MAP(ADDRMAP11_ROW_B10, addrmap11);
0703 }
0704 
0705 /* Ignore the bitmap if it's the flag value, otherwise map it */
0706 #define DDRC_CHECK_AND_MAP(bus_width, lpddr3, BIT_ID, info, addrmap) \
0707 ({ \
0708   uint32_t mapbit = DDRC_ ## BIT_ID ## _GET(addrmap); \
0709   uint32_t target_bit = DDRC_ ## BIT_ID ## _TARGET_BIT(bus_width, lpddr3); \
0710   if (mapbit != DDRC_ ## BIT_ID ## _SPECIAL) { \
0711     mapbit += DDRC_ ## BIT_ID ## _BASE; \
0712     /* account for AXI -> HIF shift */ \
0713     mapbit += 3; \
0714     info-> DDRC_ ## BIT_ID ## _TARGET |= \
0715       DDRC_MAP_BIT(info->address, mapbit, target_bit); \
0716   } \
0717 })
0718 
0719 static int decompose_address(DDR_Error_Info *info)
0720 {
0721   uint32_t addrmap0 = DDRC_READ(DDRC_ADDRMAP0_OFFSET);
0722   uint32_t addrmap1 = DDRC_READ(DDRC_ADDRMAP1_OFFSET);
0723   uint32_t addrmap2 = DDRC_READ(DDRC_ADDRMAP2_OFFSET);
0724   uint32_t addrmap3 = DDRC_READ(DDRC_ADDRMAP3_OFFSET);
0725   uint32_t addrmap4 = DDRC_READ(DDRC_ADDRMAP4_OFFSET);
0726   uint32_t addrmap5 = DDRC_READ(DDRC_ADDRMAP5_OFFSET);
0727   uint32_t addrmap6 = DDRC_READ(DDRC_ADDRMAP6_OFFSET);
0728   uint32_t addrmap7 = DDRC_READ(DDRC_ADDRMAP7_OFFSET);
0729   uint32_t addrmap8 = DDRC_READ(DDRC_ADDRMAP8_OFFSET);
0730   uint32_t addrmap9 = DDRC_READ(DDRC_ADDRMAP9_OFFSET);
0731   uint32_t addrmap10 = DDRC_READ(DDRC_ADDRMAP10_OFFSET);
0732   uint32_t addrmap11 = DDRC_READ(DDRC_ADDRMAP11_OFFSET);
0733   uint32_t mstr = DDRC_READ(DDRC_MSTR_OFFSET);
0734   uint32_t bus_width = DDRC_MSTR_DATA_BUS_WIDTH_GET(mstr);
0735   bool lpddr3 = mstr & DDRC_MSTR_LPDDR3;
0736 
0737   homogenize_row(&addrmap5, &addrmap9, &addrmap10, &addrmap11);
0738   
0739   /* Clear items that will be written to */
0740   info->rank = 0;
0741   info->bank_group = 0;
0742   info->bank = 0;
0743   info->row = 0;
0744   info->column = 0;
0745 
0746   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP0_RANK_B0, info, addrmap0);
0747   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP1_BANK_B2, info, addrmap1);
0748   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP1_BANK_B1, info, addrmap1);
0749   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP1_BANK_B0, info, addrmap1);
0750   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP2_COL_B5, info, addrmap2);
0751   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP2_COL_B4, info, addrmap2);
0752   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP2_COL_B3, info, addrmap2);
0753   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP2_COL_B2, info, addrmap2);
0754   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP3_COL_B9, info, addrmap3);
0755   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP3_COL_B8, info, addrmap3);
0756   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP3_COL_B7, info, addrmap3);
0757   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP3_COL_B6, info, addrmap3);
0758   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP4_COL_B11, info, addrmap4);
0759   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP4_COL_B10, info, addrmap4);
0760   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP5_ROW_B11, info, addrmap5);
0761   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP5_ROW_B1, info, addrmap5);
0762   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP5_ROW_B0, info, addrmap5);
0763   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP6_ROW_B15, info, addrmap6);
0764   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP6_ROW_B14, info, addrmap6);
0765   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP6_ROW_B13, info, addrmap6);
0766   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP6_ROW_B12, info, addrmap6);
0767   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP7_ROW_B17, info, addrmap7);
0768   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP7_ROW_B16, info, addrmap7);
0769   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP8_BG_B1, info, addrmap8);
0770   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP8_BG_B0, info, addrmap8);
0771   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP9_ROW_B5, info, addrmap9);
0772   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP9_ROW_B4, info, addrmap9);
0773   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP9_ROW_B3, info, addrmap9);
0774   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP9_ROW_B2, info, addrmap9);
0775   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP10_ROW_B9, info, addrmap10);
0776   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP10_ROW_B8, info, addrmap10);
0777   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP10_ROW_B7, info, addrmap10);
0778   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP10_ROW_B6, info, addrmap10);
0779   DDRC_CHECK_AND_MAP(bus_width, lpddr3, ADDRMAP11_ROW_B10, info, addrmap11);
0780 
0781   /* Column[0:1] are always statically mapped to HIF[0:1] */
0782   info->column |= (info->address >> 3) & 0x3;
0783 
0784   /* select target address */
0785   uint32_t paddr0_val = DDRC_ECCPOISONADDR0_COL_SET(0, info->column);
0786   if (info->rank) {
0787     paddr0_val |= DDRC_ECCPOISONADDR0_RANK;
0788   }
0789 
0790   uint32_t paddr1_val = DDRC_ECCPOISONADDR1_BG_SET(0, info->bank_group);
0791   paddr1_val = DDRC_ECCPOISONADDR1_BANK_SET(paddr1_val, info->bank);
0792   paddr1_val = DDRC_ECCPOISONADDR1_ROW_SET(paddr1_val, info->row);
0793   return 0;
0794 }
0795 
0796 /* DDR Controller (DDRC) ECC Config Register 1 */
0797 #define DDRC_ECCCFG1_OFFSET 0x74
0798 #define DDRC_ECCCFG1_POISON_SINGLE BSP_BIT32(1)
0799 #define DDRC_ECCCFG1_POISON_EN BSP_BIT32(0)
0800 
0801 #define DDRC_SWCTL_OFFSET 0x74
0802 #define DDRC_SWSTAT_OFFSET 0x324
0803 
0804 #define DDRC_DBGCAM_OFFSET 0x308
0805 #define DDRC_DBGCAM_WR_DATA_PIPELINE_EMPTY BSP_BIT32(28)
0806 #define DDRC_DBGCAM_RD_DATA_PIPELINE_EMPTY BSP_BIT32(27)
0807 #define DDRC_DBGCAM_DBG_WR_Q_EMPTY BSP_BIT32(26)
0808 #define DDRC_DBGCAM_DBG_RD_Q_EMPTY BSP_BIT32(25)
0809 
0810 #define DDRC_DBG1_OFFSET 0x304
0811 #define DDRC_DBG1_DIS_DQ BSP_BIT32(0)
0812 
0813 static void set_ecccfg1(volatile uint32_t *ecccfg1, uint32_t ecccfg1_val)
0814 {
0815   uint32_t dbgcam_mask = DDRC_DBGCAM_WR_DATA_PIPELINE_EMPTY |
0816     DDRC_DBGCAM_RD_DATA_PIPELINE_EMPTY | DDRC_DBGCAM_DBG_WR_Q_EMPTY |
0817     DDRC_DBGCAM_DBG_RD_Q_EMPTY;
0818   volatile uint32_t *dbgcam = (uint32_t *)(ddrc_base + DDRC_DBGCAM_OFFSET);
0819   volatile uint32_t *dbg1 = (uint32_t *)(ddrc_base + DDRC_DBG1_OFFSET);
0820 
0821   /* disable dequeueing */
0822   *dbg1 |= DDRC_DBG1_DIS_DQ;
0823   /* poll for DDRC empty state */
0824   while((*dbgcam & dbgcam_mask) != dbgcam_mask);
0825   *ecccfg1 = ecccfg1_val;
0826   /* enable dequeueing */
0827   *dbg1 &= ~DDRC_DBG1_DIS_DQ;
0828 }
0829 
0830 void zynqmp_ddr_inject_fault( bool correctable )
0831 {
0832   uint64_t poison_var;
0833   uint64_t read_var;
0834   volatile uint64_t *poison_addr = &poison_var;
0835   volatile uint32_t *ecccfg1 = (uint32_t *)(ddrc_base + DDRC_ECCCFG1_OFFSET);
0836   uint32_t ecccfg1_val = 0;
0837   volatile uint32_t *swctl = (uint32_t *)(ddrc_base + DDRC_SWCTL_OFFSET);
0838   volatile uint32_t *swstat = (uint32_t *)(ddrc_base + DDRC_SWSTAT_OFFSET);
0839   volatile uint32_t *poisonaddr0;
0840   uint32_t paddr0_val;
0841   volatile uint32_t *poisonaddr1;
0842   uint32_t paddr1_val;
0843   DDR_Error_Info info;
0844   poisonaddr0 = (uint32_t *)(ddrc_base + DDRC_ECCPOISONADDR0_OFFSET);
0845   poisonaddr1 = (uint32_t *)(ddrc_base + DDRC_ECCPOISONADDR1_OFFSET);
0846 
0847   info.address = (uint64_t)(uintptr_t)poison_addr;
0848   /* convert address to SDRAM address components */
0849   decompose_address(&info);
0850 
0851   /* select correctable/uncorrectable */
0852   ecccfg1_val &= ~DDRC_ECCCFG1_POISON_SINGLE;
0853   if (correctable) {
0854     ecccfg1_val |= DDRC_ECCCFG1_POISON_SINGLE;
0855   }
0856 
0857   /* enable poisoning */
0858   ecccfg1_val |= DDRC_ECCCFG1_POISON_EN;
0859 
0860   uint32_t isr_cookie;
0861   rtems_interrupt_local_disable(isr_cookie);
0862   /* swctl must be unset to allow modification of ecccfg1 */
0863   *swctl = 0;
0864   set_ecccfg1(ecccfg1, ecccfg1_val);
0865   *swctl = 1;
0866   rtems_interrupt_local_enable(isr_cookie);
0867 
0868   /* Wait for swctl propagation to swstat */
0869   while ((*swstat & 0x1) == 0);
0870 
0871   /* select target address */
0872   paddr0_val = DDRC_ECCPOISONADDR0_COL_SET(0, info.column);
0873   if (info.rank) {
0874     paddr0_val |= DDRC_ECCPOISONADDR0_RANK;
0875   }
0876   *poisonaddr0 = paddr0_val;
0877 
0878   paddr1_val = DDRC_ECCPOISONADDR1_BG_SET(0, info.bank_group);
0879   paddr1_val = DDRC_ECCPOISONADDR1_BANK_SET(paddr1_val, info.bank);
0880   paddr1_val = DDRC_ECCPOISONADDR1_ROW_SET(paddr1_val, info.row);
0881   *poisonaddr1 = paddr1_val;
0882 
0883   /* write to poison address */
0884   *poison_addr = 0x5555555555555555UL;
0885 
0886   /* flush cache to force write */
0887   rtems_cache_flush_multiple_data_lines(poison_addr, sizeof(*poison_addr));
0888 
0889   /* invalidate cache to force read */
0890   rtems_cache_invalidate_multiple_data_lines(poison_addr, sizeof(*poison_addr));
0891 
0892   /* Force a data sync barrier */
0893   _AARCH64_Data_synchronization_barrier();
0894 
0895   /* read from poison address to generate event */
0896   read_var = *poison_addr;
0897   read_var++;
0898 
0899   volatile uint32_t *qis = (uint32_t *)(ddr_qos_ctrl_base + DDR_QIS_OFFSET);
0900 
0901   /* disable poisoning */
0902   *swctl = 0;
0903   *ecccfg1 = 0;
0904   *swctl = 1;
0905 }
0906 #endif