3 * Developed for DENX Software Engineering GmbH.
5 * Author: Pavel Kolesnikov <concord@emcraft.com>
7 * See file CREDITS for list of people who contributed to this
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 /* define DEBUG for debugging output (obviously ;-)) */
38 #if CONFIG_POST & CFG_POST_ECC
43 * This test performs the checks ECC facility of memory.
45 #include <asm/processor.h>
50 #include "../../../board/lwmon5/sdram.h"
52 DECLARE_GLOBAL_DATA_PTR;
54 const static unsigned char syndrome_codes[] = {
55 0xF4, 0XF1, 0XEC ,0XEA, 0XE9, 0XE6, 0XE5, 0XE3,
56 0XDC, 0XDA, 0XD9, 0XD6, 0XD5, 0XD3, 0XCE, 0XCB,
57 0xB5, 0XB0, 0XAD, 0XAB, 0XA8, 0XA7, 0XA4, 0XA2,
58 0X9D, 0X9B, 0X98, 0X97, 0X94, 0X92, 0X8F, 0X8A,
59 0x75, 0x70, 0X6D, 0X6B, 0X68, 0X67, 0X64, 0X62,
60 0X5E, 0X5B, 0X58, 0X57, 0X54, 0X52, 0X4F, 0X4A,
61 0x34, 0x31, 0X2C, 0X2A, 0X29, 0X26, 0X25, 0X23,
62 0X1C, 0X1A, 0X19, 0X16, 0X15, 0X13, 0X0E, 0X0B,
63 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
66 #define ECC_START_ADDR 0x10
67 #define ECC_STOP_ADDR 0x2000
68 #define ECC_PATTERN 0x0101010101010101ull
69 #define ECC_PATTERN_CORR 0x0101010101010100ull
70 #define ECC_PATTERN_UNCORR 0x010101010101010Full
72 static int test_ecc_error(void)
75 unsigned long hdata, ldata, haddr, laddr;
80 mfsdram(DDR0_23, value);
82 for (bit = 0; bit < sizeof(syndrome_codes); bit++)
83 if (syndrome_codes[bit] == ((value >> 16) & 0xff))
86 mfsdram(DDR0_00, value);
88 if (value & DDR0_00_INT_STATUS_BIT0) {
89 debug("Bit0. A single access outside the defined PHYSICAL"
90 " memory space detected\n");
91 mfsdram(DDR0_32, laddr);
92 mfsdram(DDR0_33, haddr);
93 debug(" addr = 0x%08x%08x\n", haddr, laddr);
96 if (value & DDR0_00_INT_STATUS_BIT1) {
97 debug("Bit1. Multiple accesses outside the defined PHYSICAL"
98 " memory space detected\n");
101 if (value & DDR0_00_INT_STATUS_BIT2) {
102 debug("Bit2. Single correctable ECC event detected\n");
103 mfsdram(DDR0_38, laddr);
104 mfsdram(DDR0_39, haddr);
105 mfsdram(DDR0_40, ldata);
106 mfsdram(DDR0_41, hdata);
107 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
108 laddr, hdata, ldata, bit);
111 if (value & DDR0_00_INT_STATUS_BIT3) {
112 debug("Bit3. Multiple correctable ECC events detected\n");
113 mfsdram(DDR0_38, laddr);
114 mfsdram(DDR0_39, haddr);
115 mfsdram(DDR0_40, ldata);
116 mfsdram(DDR0_41, hdata);
117 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
118 laddr, hdata, ldata, bit);
121 if (value & DDR0_00_INT_STATUS_BIT4) {
122 debug("Bit4. Single uncorrectable ECC event detected\n");
123 mfsdram(DDR0_34, laddr);
124 mfsdram(DDR0_35, haddr);
125 mfsdram(DDR0_36, ldata);
126 mfsdram(DDR0_37, hdata);
127 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
128 laddr, hdata, ldata, bit);
131 if (value & DDR0_00_INT_STATUS_BIT5) {
132 debug("Bit5. Multiple uncorrectable ECC events detected\n");
133 mfsdram(DDR0_34, laddr);
134 mfsdram(DDR0_35, haddr);
135 mfsdram(DDR0_36, ldata);
136 mfsdram(DDR0_37, hdata);
137 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
138 laddr, hdata, ldata, bit);
141 if (value & DDR0_00_INT_STATUS_BIT6) {
142 debug("Bit6. DRAM initialization complete\n");
146 /* error status cleared */
147 mfsdram(DDR0_00, value);
148 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
153 static int test_ecc(unsigned long ecc_addr)
155 volatile unsigned long long *ecc_mem;
157 unsigned long ecc_data;
158 volatile unsigned long *lecc_mem;
165 ecc_mem = (unsigned long long *)ecc_addr;
166 lecc_mem = (ulong *)ecc_addr;
167 *ecc_mem = ECC_PATTERN;
168 pret = test_ecc_error();
173 mfsdram(DDR0_22, value);
174 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
175 | DDR0_22_CTRL_RAW_ECC_DISABLE);
177 /* injecting error */
178 *ecc_mem = ECC_PATTERN_CORR;
181 mfsdram(DDR0_22, value);
182 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
183 | DDR0_22_CTRL_RAW_ECC_ENABLE);
185 ecc_data = *lecc_mem;
186 pret = test_ecc_error();
187 /* if read data ok, 1 correctable error must be fixed */
191 /* test for uncorrectable error */
192 /* disconnect from ecc storage */
193 mfsdram(DDR0_22, value);
194 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
195 | DDR0_22_CTRL_RAW_NO_ECC_RAM);
197 /* injecting multiply bit error */
199 *ecc_mem = ECC_PATTERN_UNCORR;
202 mfsdram(DDR0_22, value);
203 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
204 | DDR0_22_CTRL_RAW_ECC_ENABLE);
206 ecc_data = *lecc_mem;
207 /* what the data should be read? */
209 pret = test_ecc_error();
210 /* info about uncorrectable error must appear */
220 int ecc_post_test (int flags)
231 mfsdram(DDR0_01, value);
232 mtsdram(DDR0_01, (value &~ DDR0_01_INT_MASK_MASK)
233 | DDR0_01_INT_MASK_ALL_OFF);
235 /* clear error status */
236 mfsdram(DDR0_00, value);
237 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
239 /* enable full support of ECC */
240 mfsdram(DDR0_22, value);
241 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
242 | DDR0_22_CTRL_RAW_ECC_ENABLE);
244 for (iaddr = ECC_START_ADDR; iaddr < ECC_STOP_ADDR; iaddr += iaddr) {
245 ret = test_ecc(iaddr);
250 /* clear error status */
251 mfsdram(DDR0_00, value);
252 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
255 * Clear possible errors resulting from ECC testing.
256 * If not done, then we could get an interrupt later on when
257 * exceptions are enabled.
259 set_mcsr(get_mcsr());
266 #endif /* CONFIG_POST & CFG_POST_ECC */
267 #endif /* CONFIG_POST */