]> git.ipfire.org Git - people/ms/u-boot.git/blame - post/cpu/ppc4xx/denali_ecc.c
drivers, block: remove sil680 driver
[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 *
1a459660 7 * SPDX-License-Identifier: GPL-2.0+
531e3e8b
PK
8 */
9
10/* define DEBUG for debugging output (obviously ;-)) */
11#if 0
12#define DEBUG
13#endif
14
15#include <common.h>
16#include <watchdog.h>
17
0a51e924 18#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
531e3e8b
PK
19
20#include <post.h>
21
6d0f6bcf 22#if CONFIG_POST & CONFIG_SYS_POST_ECC
531e3e8b
PK
23
24/*
25 * MEMORY ECC test
26 *
27 * This test performs the checks ECC facility of memory.
28 */
29#include <asm/processor.h>
30#include <asm/mmu.h>
31#include <asm/io.h>
b36df561 32#include <asm/ppc440.h>
531e3e8b 33
531e3e8b
PK
34DECLARE_GLOBAL_DATA_PTR;
35
d62b247d 36#if defined(DEBUG)
4b3cc6ec 37const static uint8_t syndrome_codes[] = {
0d9cdeac 38 0xF4, 0XF1, 0XEC, 0XEA, 0XE9, 0XE6, 0XE5, 0XE3,
531e3e8b
PK
39 0XDC, 0XDA, 0XD9, 0XD6, 0XD5, 0XD3, 0XCE, 0XCB,
40 0xB5, 0XB0, 0XAD, 0XAB, 0XA8, 0XA7, 0XA4, 0XA2,
41 0X9D, 0X9B, 0X98, 0X97, 0X94, 0X92, 0X8F, 0X8A,
42 0x75, 0x70, 0X6D, 0X6B, 0X68, 0X67, 0X64, 0X62,
43 0X5E, 0X5B, 0X58, 0X57, 0X54, 0X52, 0X4F, 0X4A,
44 0x34, 0x31, 0X2C, 0X2A, 0X29, 0X26, 0X25, 0X23,
45 0X1C, 0X1A, 0X19, 0X16, 0X15, 0X13, 0X0E, 0X0B,
46 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
47};
d62b247d 48#endif
531e3e8b
PK
49
50#define ECC_START_ADDR 0x10
51#define ECC_STOP_ADDR 0x2000
a724a9b4
LJ
52#define ECC_PATTERN 0x01010101
53#define ECC_PATTERN_CORR 0x11010101
4b3cc6ec 54#define ECC_PATTERN_UNCORR 0x61010101
531e3e8b 55
4b3cc6ec 56inline static void disable_ecc(void)
531e3e8b 57{
4b3cc6ec 58 uint32_t value;
531e3e8b 59
4b3cc6ec
LJ
60 sync(); /* Wait for any pending memory accesses to complete. */
61 mfsdram(DDR0_22, value);
62 mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK)
63 | DDR0_22_CTRL_RAW_ECC_DISABLE);
64}
531e3e8b 65
4b3cc6ec
LJ
66inline static void clear_and_enable_ecc(void)
67{
68 uint32_t value;
531e3e8b 69
4b3cc6ec 70 sync(); /* Wait for any pending memory accesses to complete. */
531e3e8b 71 mfsdram(DDR0_00, value);
4b3cc6ec
LJ
72 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
73 mfsdram(DDR0_22, value);
74 mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK)
75 | DDR0_22_CTRL_RAW_ECC_ENABLE);
76}
77
78static uint32_t get_ecc_status(void)
79{
80 uint32_t int_status;
81#if defined(DEBUG)
82 uint8_t syndrome;
83 uint32_t hdata, ldata, haddr, laddr;
84 uint32_t value;
85#endif
86
87 mfsdram(DDR0_00, int_status);
88 int_status &= DDR0_00_INT_STATUS_MASK;
531e3e8b 89
4b3cc6ec
LJ
90#if defined(DEBUG)
91 if (int_status & (DDR0_00_INT_STATUS_BIT0 | DDR0_00_INT_STATUS_BIT1)) {
531e3e8b
PK
92 mfsdram(DDR0_32, laddr);
93 mfsdram(DDR0_33, haddr);
4b3cc6ec
LJ
94 haddr &= 0x00000001;
95 if (int_status & DDR0_00_INT_STATUS_BIT1)
96 debug("Multiple accesses");
97 else
98 debug("A single access");
99
100 debug(" outside the defined physical memory space detected\n"
101 " addr = 0x%01x%08x\n", haddr, laddr);
531e3e8b 102 }
4b3cc6ec
LJ
103 if (int_status & (DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT3)) {
104 unsigned int bit;
105
106 mfsdram(DDR0_23, value);
107 syndrome = (value >> 16) & 0xff;
108 for (bit = 0; bit < sizeof(syndrome_codes); bit++)
109 if (syndrome_codes[bit] == syndrome)
110 break;
111
531e3e8b
PK
112 mfsdram(DDR0_38, laddr);
113 mfsdram(DDR0_39, haddr);
4b3cc6ec 114 haddr &= 0x00000001;
531e3e8b
PK
115 mfsdram(DDR0_40, ldata);
116 mfsdram(DDR0_41, hdata);
4b3cc6ec
LJ
117 if (int_status & DDR0_00_INT_STATUS_BIT3)
118 debug("Multiple correctable ECC events");
119 else
120 debug("Single correctable ECC event");
121
122 debug(" detected\n 0x%01x%08x - 0x%08x%08x, bit - %d\n",
123 haddr, laddr, hdata, ldata, bit);
531e3e8b 124 }
4b3cc6ec
LJ
125 if (int_status & (DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT5)) {
126 mfsdram(DDR0_23, value);
127 syndrome = (value >> 8) & 0xff;
531e3e8b
PK
128 mfsdram(DDR0_34, laddr);
129 mfsdram(DDR0_35, haddr);
4b3cc6ec 130 haddr &= 0x00000001;
531e3e8b
PK
131 mfsdram(DDR0_36, ldata);
132 mfsdram(DDR0_37, hdata);
4b3cc6ec
LJ
133 if (int_status & DDR0_00_INT_STATUS_BIT5)
134 debug("Multiple uncorrectable ECC events");
135 else
136 debug("Single uncorrectable ECC event");
137
138 debug(" detected\n 0x%01x%08x - 0x%08x%08x, "
139 "syndrome - 0x%02x\n",
140 haddr, laddr, hdata, ldata, syndrome);
531e3e8b 141 }
4b3cc6ec
LJ
142 if (int_status & DDR0_00_INT_STATUS_BIT6)
143 debug("DRAM initialization complete\n");
144#endif /* defined(DEBUG) */
531e3e8b 145
4b3cc6ec 146 return int_status;
531e3e8b
PK
147}
148
4b3cc6ec 149static int test_ecc(uint32_t ecc_addr)
531e3e8b 150{
4b3cc6ec
LJ
151 uint32_t value;
152 volatile uint32_t *const ecc_mem = (volatile uint32_t *)ecc_addr;
a724a9b4 153 int ret = 0;
531e3e8b 154
531e3e8b
PK
155 WATCHDOG_RESET();
156
4b3cc6ec
LJ
157 debug("Entering test_ecc(0x%08x)\n", ecc_addr);
158 /* Set up correct ECC in memory */
159 disable_ecc();
160 clear_and_enable_ecc();
a724a9b4
LJ
161 out_be32(ecc_mem, ECC_PATTERN);
162 out_be32(ecc_mem + 1, ECC_PATTERN);
28e94bb2 163 ppcDcbf((u32)ecc_mem);
4b3cc6ec
LJ
164
165 /* Verify no ECC error reading back */
166 value = in_be32(ecc_mem);
167 disable_ecc();
168 if (ECC_PATTERN != value) {
169 debug("Data read error (no-error case): "
170 "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value);
171 ret = 1;
172 }
173 value = get_ecc_status();
174 if (0x00000000 != value) {
175 /* Expected no ECC status reported */
176 debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n",
177 0x00000000, value);
531e3e8b 178 ret = 1;
a724a9b4 179 }
531e3e8b 180
4b3cc6ec 181 /* Test for correctable error by creating a one-bit error */
a724a9b4 182 out_be32(ecc_mem, ECC_PATTERN_CORR);
28e94bb2 183 ppcDcbf((u32)ecc_mem);
4b3cc6ec
LJ
184 clear_and_enable_ecc();
185 value = in_be32(ecc_mem);
186 disable_ecc();
187 /* Test that the corrected data was read */
188 if (ECC_PATTERN != value) {
189 debug("Data read error (correctable-error case): "
190 "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value);
191 ret = 1;
192 }
193 value = get_ecc_status();
194 if ((DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT7) != value) {
195 /* Expected a single correctable error reported */
196 debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n",
197 DDR0_00_INT_STATUS_BIT2, value);
531e3e8b 198 ret = 1;
a724a9b4 199 }
531e3e8b 200
4b3cc6ec 201 /* Test for uncorrectable error by creating a two-bit error */
a724a9b4 202 out_be32(ecc_mem, ECC_PATTERN_UNCORR);
28e94bb2 203 ppcDcbf((u32)ecc_mem);
4b3cc6ec
LJ
204 clear_and_enable_ecc();
205 value = in_be32(ecc_mem);
206 disable_ecc();
207 /* Test that the corrected data was read */
208 if (ECC_PATTERN_UNCORR != value) {
209 debug("Data read error (uncorrectable-error case): "
210 "expected 0x%08x, read 0x%08x\n", ECC_PATTERN_UNCORR,
211 value);
212 ret = 1;
213 }
214 value = get_ecc_status();
215 if ((DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT7) != value) {
216 /* Expected a single uncorrectable error reported */
217 debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n",
218 DDR0_00_INT_STATUS_BIT4, value);
531e3e8b 219 ret = 1;
a724a9b4 220 }
4b3cc6ec
LJ
221
222 /* Remove error from SDRAM and enable ECC. */
a724a9b4 223 out_be32(ecc_mem, ECC_PATTERN);
28e94bb2 224 ppcDcbf((u32)ecc_mem);
4b3cc6ec 225 clear_and_enable_ecc();
531e3e8b 226
531e3e8b
PK
227 return ret;
228}
229
4b3cc6ec 230int ecc_post_test(int flags)
531e3e8b
PK
231{
232 int ret = 0;
4b3cc6ec
LJ
233 uint32_t value;
234 uint32_t iaddr;
531e3e8b 235
a724a9b4
LJ
236 mfsdram(DDR0_22, value);
237 if (0x3 != DDR0_22_CTRL_RAW_DECODE(value)) {
238 debug("SDRAM ECC not enabled, skipping ECC POST.\n");
239 return 0;
240 }
241
4b3cc6ec 242 /* Mask all interrupts. */
531e3e8b 243 mfsdram(DDR0_01, value);
0d9cdeac 244 mtsdram(DDR0_01, (value & ~DDR0_01_INT_MASK_MASK)
531e3e8b
PK
245 | DDR0_01_INT_MASK_ALL_OFF);
246
a724a9b4 247 for (iaddr = ECC_START_ADDR; iaddr <= ECC_STOP_ADDR; iaddr += iaddr) {
531e3e8b
PK
248 ret = test_ecc(iaddr);
249 if (ret)
250 break;
251 }
ea9f6bce 252 /*
4b3cc6ec
LJ
253 * Clear possible errors resulting from ECC testing. (If not done, we
254 * we could get an interrupt later on when exceptions are enabled.)
ea9f6bce
SR
255 */
256 set_mcsr(get_mcsr());
4b3cc6ec 257 debug("ecc_post_test() returning %d\n", ret);
531e3e8b 258 return ret;
531e3e8b 259}
6d0f6bcf 260#endif /* CONFIG_POST & CONFIG_SYS_POST_ECC */
0a51e924 261#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */