1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <common.h>
29#include <mpc83xx.h>
30#include <watchdog.h>
31#include <asm/io.h>
32#include <post.h>
33
34#if CONFIG_POST & CONFIG_SYS_POST_ECC
35
36
37
38
39
40static inline void ecc_clear(ddr83xx_t *ddr)
41{
42
43 __raw_writel(0, &ddr->capture_address);
44 __raw_writel(0, &ddr->capture_data_hi);
45 __raw_writel(0, &ddr->capture_data_lo);
46 __raw_writel(0, &ddr->capture_ecc);
47 __raw_writel(0, &ddr->capture_attributes);
48
49
50 out_be32(&ddr->err_sbe, 1 << ECC_ERROR_MAN_SBET_SHIFT);
51
52
53 out_be32(&ddr->err_detect, ECC_ERROR_DETECT_MME |\
54 ECC_ERROR_DETECT_MBE |\
55 ECC_ERROR_DETECT_SBE |\
56 ECC_ERROR_DETECT_MSE);
57
58 isync();
59}
60
61int ecc_post_test(int flags)
62{
63 int ret = 0;
64 int int_state;
65 int errbit;
66 u32 pattern[2], writeback[2], retval[2];
67 ddr83xx_t *ddr = &((immap_t *)CONFIG_SYS_IMMR)->ddr;
68 volatile u64 *addr = (u64 *)CONFIG_SYS_POST_ECC_START_ADDR;
69
70
71 pattern[0] = 0xfedcba98UL;
72 pattern[1] = 0x76543210UL;
73
74
75 writeback[0] = ~pattern[0];
76 writeback[1] = ~pattern[1];
77
78
79 if (__raw_readl(&ddr->err_disable) & ECC_ERROR_ENABLE) {
80 debug("DDR's ECC is not enabled, skipping the ECC POST.\n");
81 return 0;
82 }
83
84 int_state = disable_interrupts();
85 icache_enable();
86
87#ifdef CONFIG_DDR_32BIT
88
89#error "Add ECC POST support for CONFIG_DDR_32BIT here!"
90#else
91 for (addr = (u64*)CONFIG_SYS_POST_ECC_START_ADDR, errbit=0;
92 addr < (u64*)CONFIG_SYS_POST_ECC_STOP_ADDR; addr++, errbit++ ) {
93
94 WATCHDOG_RESET();
95
96 ecc_clear(ddr);
97
98
99 setbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN);
100 sync();
101 isync();
102
103
104 if (errbit < 32) {
105 __raw_writel(1 << errbit, &ddr->data_err_inject_lo);
106 __raw_writel(0, &ddr->data_err_inject_hi);
107 } else {
108 __raw_writel(0, &ddr->data_err_inject_lo);
109 __raw_writel(1<<(errbit-32), &ddr->data_err_inject_hi);
110 }
111 sync();
112 isync();
113
114
115 ppcDWstore((u32*)addr, pattern);
116 sync();
117
118
119 clrbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN);
120 sync();
121 isync();
122
123
124 ppcDWload((u32*)addr, retval);
125 sync();
126
127 if (!(__raw_readl(&ddr->err_detect) & ECC_ERROR_DETECT_SBE) ||
128 (__raw_readl(&ddr->data_err_inject_hi) !=
129 (__raw_readl(&ddr->capture_data_hi) ^ pattern[0])) ||
130 (__raw_readl(&ddr->data_err_inject_lo) !=
131 (__raw_readl(&ddr->capture_data_lo) ^ pattern[1]))) {
132
133 post_log("ECC failed to detect SBE error at %08x, "
134 "SBE injection mask %08x-%08x, wrote "
135 "%08x-%08x, read %08x-%08x\n", addr,
136 ddr->data_err_inject_hi,
137 ddr->data_err_inject_lo,
138 pattern[0], pattern[1],
139 retval[0], retval[1]);
140
141 printf("ERR_DETECT Reg: %08x\n", ddr->err_detect);
142 printf("ECC CAPTURE_DATA Reg: %08x-%08x\n",
143 ddr->capture_data_hi, ddr->capture_data_lo);
144 ret = 1;
145 break;
146 }
147
148
149 ppcDWstore((u32*)addr, writeback);
150 sync();
151 isync();
152
153 errbit %= 63;
154 }
155#endif
156
157 ecc_clear(ddr);
158
159 icache_disable();
160
161 if (int_state)
162 enable_interrupts();
163
164 return ret;
165}
166#endif
167