]> git.ipfire.org Git - people/ms/u-boot.git/blame - post/cpu/ppc4xx/denali_ecc.c
Merge branch 'master' of /home/stefan/git/u-boot/u-boot
[people/ms/u-boot.git] / post / cpu / ppc4xx / denali_ecc.c
CommitLineData
531e3e8b
PK
1/*
2 * (C) Copyright 2007
3 * Developed for DENX Software Engineering GmbH.
4 *
5 * Author: Pavel Kolesnikov <concord@emcraft.com>
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
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.
14 *
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.
19 *
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,
23 * MA 02111-1307 USA
24 */
25
26/* define DEBUG for debugging output (obviously ;-)) */
27#if 0
28#define DEBUG
29#endif
30
31#include <common.h>
32#include <watchdog.h>
33
a724a9b4 34#if defined(CONFIG_POST) && (defined(CONFIG_440EPX) || defined(CONFIG_440GRX))
531e3e8b
PK
35
36#include <post.h>
37
38#if CONFIG_POST & CFG_POST_ECC
39
40/*
41 * MEMORY ECC test
42 *
43 * This test performs the checks ECC facility of memory.
44 */
45#include <asm/processor.h>
46#include <asm/mmu.h>
47#include <asm/io.h>
48#include <ppc440.h>
49
531e3e8b
PK
50DECLARE_GLOBAL_DATA_PTR;
51
52const static unsigned char syndrome_codes[] = {
0d9cdeac 53 0xF4, 0XF1, 0XEC, 0XEA, 0XE9, 0XE6, 0XE5, 0XE3,
531e3e8b
PK
54 0XDC, 0XDA, 0XD9, 0XD6, 0XD5, 0XD3, 0XCE, 0XCB,
55 0xB5, 0XB0, 0XAD, 0XAB, 0XA8, 0XA7, 0XA4, 0XA2,
56 0X9D, 0X9B, 0X98, 0X97, 0X94, 0X92, 0X8F, 0X8A,
57 0x75, 0x70, 0X6D, 0X6B, 0X68, 0X67, 0X64, 0X62,
58 0X5E, 0X5B, 0X58, 0X57, 0X54, 0X52, 0X4F, 0X4A,
59 0x34, 0x31, 0X2C, 0X2A, 0X29, 0X26, 0X25, 0X23,
60 0X1C, 0X1A, 0X19, 0X16, 0X15, 0X13, 0X0E, 0X0B,
61 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
62};
63
64#define ECC_START_ADDR 0x10
65#define ECC_STOP_ADDR 0x2000
a724a9b4
LJ
66#define ECC_PATTERN 0x01010101
67#define ECC_PATTERN_CORR 0x11010101
68#define ECC_PATTERN_UNCORR 0xF1010101
531e3e8b
PK
69
70static int test_ecc_error(void)
71{
72 unsigned long value;
73 unsigned long hdata, ldata, haddr, laddr;
74 unsigned int bit;
75
76 int ret = 0;
77
78 mfsdram(DDR0_23, value);
79
80 for (bit = 0; bit < sizeof(syndrome_codes); bit++)
81 if (syndrome_codes[bit] == ((value >> 16) & 0xff))
82 break;
83
84 mfsdram(DDR0_00, value);
85
86 if (value & DDR0_00_INT_STATUS_BIT0) {
87 debug("Bit0. A single access outside the defined PHYSICAL"
88 " memory space detected\n");
89 mfsdram(DDR0_32, laddr);
90 mfsdram(DDR0_33, haddr);
91 debug(" addr = 0x%08x%08x\n", haddr, laddr);
92 ret = 1;
93 }
94 if (value & DDR0_00_INT_STATUS_BIT1) {
95 debug("Bit1. Multiple accesses outside the defined PHYSICAL"
96 " memory space detected\n");
97 ret = 2;
98 }
99 if (value & DDR0_00_INT_STATUS_BIT2) {
100 debug("Bit2. Single correctable ECC event detected\n");
101 mfsdram(DDR0_38, laddr);
102 mfsdram(DDR0_39, haddr);
103 mfsdram(DDR0_40, ldata);
104 mfsdram(DDR0_41, hdata);
105 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
106 laddr, hdata, ldata, bit);
107 ret = 3;
108 }
109 if (value & DDR0_00_INT_STATUS_BIT3) {
110 debug("Bit3. Multiple correctable ECC events detected\n");
111 mfsdram(DDR0_38, laddr);
112 mfsdram(DDR0_39, haddr);
113 mfsdram(DDR0_40, ldata);
114 mfsdram(DDR0_41, hdata);
115 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
116 laddr, hdata, ldata, bit);
117 ret = 4;
118 }
119 if (value & DDR0_00_INT_STATUS_BIT4) {
120 debug("Bit4. Single uncorrectable ECC event detected\n");
121 mfsdram(DDR0_34, laddr);
122 mfsdram(DDR0_35, haddr);
123 mfsdram(DDR0_36, ldata);
124 mfsdram(DDR0_37, hdata);
125 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
126 laddr, hdata, ldata, bit);
127 ret = 5;
128 }
129 if (value & DDR0_00_INT_STATUS_BIT5) {
130 debug("Bit5. Multiple uncorrectable ECC events detected\n");
131 mfsdram(DDR0_34, laddr);
132 mfsdram(DDR0_35, haddr);
133 mfsdram(DDR0_36, ldata);
134 mfsdram(DDR0_37, hdata);
135 debug(" 0x%08x - 0x%08x%08x, bit - %d\n",
136 laddr, hdata, ldata, bit);
137 ret = 6;
138 }
139 if (value & DDR0_00_INT_STATUS_BIT6) {
140 debug("Bit6. DRAM initialization complete\n");
141 ret = 7;
142 }
143
144 /* error status cleared */
145 mfsdram(DDR0_00, value);
146 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
147
148 return ret;
149}
150
151static int test_ecc(unsigned long ecc_addr)
152{
531e3e8b 153 unsigned long value;
a724a9b4
LJ
154 volatile unsigned *const ecc_mem = (volatile unsigned *) ecc_addr;
155 int pret;
156 int ret = 0;
531e3e8b
PK
157
158 sync();
159 eieio();
160 WATCHDOG_RESET();
161
a724a9b4
LJ
162 debug("Entering test_ecc(0x%08lX)\n", ecc_addr);
163 out_be32(ecc_mem, ECC_PATTERN);
164 out_be32(ecc_mem + 1, ECC_PATTERN);
165 in_be32(ecc_mem);
531e3e8b 166 pret = test_ecc_error();
a724a9b4
LJ
167 if (pret != 0) {
168 debug("pret: expected 0, got %d\n", pret);
531e3e8b 169 ret = 1;
a724a9b4
LJ
170 }
171 /* test for correctable error */
172 /* disconnect from ecc storage */
531e3e8b 173 mfsdram(DDR0_22, value);
0d9cdeac 174 mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK)
531e3e8b
PK
175 | DDR0_22_CTRL_RAW_ECC_DISABLE);
176
a724a9b4
LJ
177 /* creating (correctable) single-bit error */
178 out_be32(ecc_mem, ECC_PATTERN_CORR);
531e3e8b
PK
179
180 /* enable ecc */
181 mfsdram(DDR0_22, value);
0d9cdeac 182 mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK)
531e3e8b 183 | DDR0_22_CTRL_RAW_ECC_ENABLE);
a724a9b4
LJ
184 sync();
185 eieio();
531e3e8b 186
a724a9b4 187 in_be32(ecc_mem);
531e3e8b
PK
188 pret = test_ecc_error();
189 /* if read data ok, 1 correctable error must be fixed */
a724a9b4
LJ
190 if (pret != 3) {
191 debug("pret: expected 3, got %d\n", pret);
531e3e8b 192 ret = 1;
a724a9b4 193 }
531e3e8b
PK
194 /* test for uncorrectable error */
195 /* disconnect from ecc storage */
196 mfsdram(DDR0_22, value);
0d9cdeac 197 mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK)
531e3e8b
PK
198 | DDR0_22_CTRL_RAW_NO_ECC_RAM);
199
a724a9b4
LJ
200 /* creating (uncorrectable) multiple-bit error */
201 out_be32(ecc_mem, ECC_PATTERN_UNCORR);
531e3e8b
PK
202
203 /* enable ecc */
204 mfsdram(DDR0_22, value);
0d9cdeac 205 mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK)
531e3e8b 206 | DDR0_22_CTRL_RAW_ECC_ENABLE);
a724a9b4
LJ
207 sync();
208 eieio();
531e3e8b 209
a724a9b4 210 in_be32(ecc_mem);
531e3e8b
PK
211 pret = test_ecc_error();
212 /* info about uncorrectable error must appear */
a724a9b4
LJ
213 if (pret != 5) {
214 debug("pret: expected 5, got %d\n", pret);
531e3e8b 215 ret = 1;
a724a9b4
LJ
216 }
217 /* remove error from SDRAM */
218 out_be32(ecc_mem, ECC_PATTERN);
219 /* clear error caused by read-modify-write */
220 mfsdram(DDR0_00, value);
221 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
531e3e8b
PK
222
223 sync();
224 eieio();
531e3e8b
PK
225 return ret;
226}
227
228int ecc_post_test (int flags)
229{
230 int ret = 0;
231 unsigned long value;
232 unsigned long iaddr;
233
531e3e8b
PK
234 sync();
235 eieio();
236
a724a9b4
LJ
237 mfsdram(DDR0_22, value);
238 if (0x3 != DDR0_22_CTRL_RAW_DECODE(value)) {
239 debug("SDRAM ECC not enabled, skipping ECC POST.\n");
240 return 0;
241 }
242
531e3e8b
PK
243 /* mask all int */
244 mfsdram(DDR0_01, value);
0d9cdeac 245 mtsdram(DDR0_01, (value & ~DDR0_01_INT_MASK_MASK)
531e3e8b
PK
246 | DDR0_01_INT_MASK_ALL_OFF);
247
248 /* clear error status */
249 mfsdram(DDR0_00, value);
250 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
251
a724a9b4 252 for (iaddr = ECC_START_ADDR; iaddr <= ECC_STOP_ADDR; iaddr += iaddr) {
531e3e8b
PK
253 ret = test_ecc(iaddr);
254 if (ret)
255 break;
256 }
ea9f6bce
SR
257 /*
258 * Clear possible errors resulting from ECC testing.
259 * If not done, then we could get an interrupt later on when
260 * exceptions are enabled.
261 */
262 set_mcsr(get_mcsr());
531e3e8b
PK
263 return ret;
264
265}
531e3e8b 266#endif /* CONFIG_POST & CFG_POST_ECC */
a724a9b4 267#endif /* defined(CONFIG_POST) && ... */