coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
raminit_rcomp_calibration.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <delay.h>
5 #include <console/console.h>
6 #include "gm45.h"
7 
8 static const int ddr3_lookup_schedule[6][2] = {
9  { 0, 1 }, { 2, 3 }, { 4, 5 }, { 4, 5 }, { 6, 7 }, { 6, 7 }
10 };
11 /* Look-up table:
12  * a1step X idx X (group || pull-up/-down)
13  */
14 static const u8 ddr3_lut[2][64][8] = {
15  { /* Stepping B3 and below. */
16  { 8, 8, 3, 3, 3, 3, 5, 7 },
17  { 8, 8, 3, 3, 3, 3, 5, 7 },
18  { 8, 8, 3, 3, 3, 3, 5, 7 },
19  { 8, 8, 3, 3, 3, 3, 5, 7 },
20  { 8, 8, 3, 3, 3, 3, 5, 7 },
21  { 8, 8, 3, 3, 3, 3, 5, 7 },
22  { 8, 8, 3, 3, 3, 3, 5, 7 },
23  { 8, 8, 3, 3, 3, 3, 5, 7 },
24  { 8, 8, 3, 3, 3, 3, 5, 7 },
25  { 8, 8, 3, 3, 3, 3, 5, 7 },
26  { 8, 8, 3, 3, 3, 3, 5, 7 },
27  { 8, 8, 3, 3, 3, 3, 5, 7 },
28  { 8, 8, 3, 3, 3, 3, 5, 7 },
29  { 8, 8, 3, 3, 3, 3, 5, 7 },
30  { 8, 8, 3, 3, 3, 3, 5, 7 },
31  { 8, 8, 3, 3, 3, 3, 5, 7 },
32  { 8, 8, 3, 3, 3, 3, 5, 7 },
33  { 8, 8, 3, 3, 3, 3, 5, 7 },
34  { 8, 8, 3, 3, 3, 3, 5, 7 },
35  { 8, 8, 3, 3, 3, 3, 5, 7 },
36  { 8, 8, 3, 3, 3, 3, 5, 7 },
37  { 8, 8, 3, 3, 3, 3, 5, 7 },
38  { 8, 8, 3, 3, 3, 3, 5, 7 },
39  { 8, 8, 3, 3, 3, 3, 5, 7 },
40  { 8, 8, 3, 3, 3, 3, 5, 7 },
41  { 8, 8, 3, 3, 3, 3, 5, 7 },
42  { 9, 9, 3, 3, 3, 3, 6, 7 },
43  { 9, 9, 3, 3, 3, 3, 6, 7 },
44  { 10, 10, 3, 3, 3, 3, 7, 8 },
45  { 11, 10, 3, 3, 3, 3, 7, 8 },
46  { 12, 11, 3, 3, 3, 3, 8, 9 },
47  { 13, 11, 3, 3, 3, 3, 9, 9 },
48  { 14, 12, 3, 3, 3, 3, 9, 10 },
49  { 15, 13, 3, 3, 3, 3, 9, 10 },
50  { 16, 14, 3, 3, 3, 3, 9, 11 },
51  { 18, 16, 3, 3, 3, 3, 10, 12 },
52  { 20, 18, 4, 3, 4, 4, 10, 12 },
53  { 22, 22, 4, 4, 4, 4, 11, 12 },
54  { 24, 24, 4, 4, 4, 4, 11, 12 },
55  { 28, 26, 4, 4, 4, 4, 12, 12 },
56  { 32, 28, 5, 4, 5, 5, 12, 12 },
57  { 36, 32, 5, 5, 5, 5, 13, 13 },
58  { 40, 36, 5, 5, 5, 5, 14, 13 },
59  { 43, 40, 5, 5, 5, 5, 15, 14 },
60  { 43, 43, 5, 5, 6, 5, 15, 14 },
61  { 43, 43, 6, 5, 6, 5, 15, 15 },
62  { 43, 43, 6, 5, 6, 6, 15, 15 },
63  { 43, 43, 6, 6, 6, 6, 15, 15 },
64  { 43, 43, 6, 6, 7, 6, 15, 15 },
65  { 43, 43, 7, 6, 7, 6, 15, 15 },
66  { 43, 43, 7, 7, 7, 7, 15, 15 },
67  { 43, 43, 7, 7, 7, 7, 15, 15 },
68  { 43, 43, 7, 7, 7, 7, 15, 15 },
69  { 43, 43, 8, 7, 8, 7, 15, 15 },
70  { 43, 43, 8, 8, 8, 8, 15, 15 },
71  { 43, 43, 8, 8, 8, 8, 15, 15 },
72  { 43, 43, 8, 8, 8, 8, 15, 15 },
73  { 43, 43, 8, 8, 8, 8, 15, 15 },
74  { 43, 43, 8, 8, 8, 8, 15, 15 },
75  { 43, 43, 8, 8, 8, 8, 15, 15 },
76  { 43, 43, 8, 8, 8, 8, 15, 15 },
77  { 43, 43, 8, 8, 8, 8, 15, 15 },
78  { 43, 43, 8, 8, 8, 8, 15, 15 },
79  { 43, 43, 8, 8, 8, 8, 15, 15 },
80  },
81  { /* Stepping A1 and above. */
82  { 8, 8, 3, 3, 3, 3, 5, 5 },
83  { 8, 8, 3, 3, 3, 3, 5, 5 },
84  { 8, 8, 3, 3, 3, 3, 5, 5 },
85  { 8, 8, 3, 3, 3, 3, 5, 5 },
86  { 8, 8, 3, 3, 3, 3, 5, 5 },
87  { 8, 8, 3, 3, 3, 3, 5, 5 },
88  { 8, 8, 3, 3, 3, 3, 5, 5 },
89  { 8, 8, 3, 3, 3, 3, 5, 5 },
90  { 8, 8, 3, 3, 3, 3, 5, 5 },
91  { 8, 8, 3, 3, 3, 3, 5, 5 },
92  { 8, 8, 3, 3, 3, 3, 5, 5 },
93  { 8, 8, 3, 3, 3, 3, 5, 5 },
94  { 8, 8, 3, 3, 3, 3, 5, 5 },
95  { 8, 8, 3, 3, 3, 3, 5, 5 },
96  { 8, 8, 3, 3, 3, 3, 5, 5 },
97  { 8, 8, 3, 3, 3, 3, 5, 5 },
98  { 8, 8, 3, 3, 3, 3, 5, 5 },
99  { 8, 8, 3, 3, 3, 3, 5, 5 },
100  { 8, 8, 3, 3, 3, 3, 5, 5 },
101  { 8, 8, 3, 3, 3, 3, 5, 5 },
102  { 8, 8, 3, 3, 3, 3, 5, 5 },
103  { 8, 8, 3, 3, 3, 3, 5, 5 },
104  { 8, 8, 3, 3, 3, 3, 5, 5 },
105  { 8, 8, 3, 3, 3, 3, 5, 5 },
106  { 8, 8, 3, 3, 3, 3, 5, 5 },
107  { 8, 8, 3, 3, 3, 3, 5, 5 },
108  { 9, 9, 3, 3, 3, 3, 6, 6 },
109  { 9, 9, 3, 3, 3, 3, 6, 6 },
110  { 10, 10, 3, 3, 3, 3, 7, 7 },
111  { 10, 10, 3, 3, 3, 3, 7, 7 },
112  { 12, 11, 3, 3, 3, 3, 8, 8 },
113  { 13, 11, 3, 3, 3, 3, 9, 9 },
114  { 14, 12, 3, 3, 3, 3, 9, 9 },
115  { 15, 13, 3, 3, 3, 3, 9, 9 },
116  { 16, 14, 3, 3, 3, 3, 9, 9 },
117  { 18, 16, 3, 3, 3, 3, 10, 10 },
118  { 20, 18, 4, 3, 4, 4, 10, 10 },
119  { 22, 22, 4, 4, 4, 4, 11, 11 },
120  { 24, 24, 4, 4, 4, 4, 11, 11 },
121  { 28, 26, 4, 4, 4, 4, 12, 12 },
122  { 32, 28, 5, 4, 5, 5, 12, 12 },
123  { 36, 32, 5, 5, 5, 5, 13, 13 },
124  { 40, 36, 5, 5, 5, 5, 14, 14 },
125  { 43, 40, 5, 5, 5, 5, 15, 15 },
126  { 43, 43, 5, 5, 6, 5, 15, 15 },
127  { 43, 43, 6, 5, 6, 5, 15, 15 },
128  { 43, 43, 6, 5, 6, 6, 15, 15 },
129  { 43, 43, 6, 6, 6, 6, 15, 15 },
130  { 43, 43, 6, 6, 7, 6, 15, 15 },
131  { 43, 43, 7, 6, 7, 6, 15, 15 },
132  { 43, 43, 7, 7, 7, 7, 15, 15 },
133  { 43, 43, 7, 7, 7, 7, 15, 15 },
134  { 43, 43, 7, 7, 7, 7, 15, 15 },
135  { 43, 43, 8, 7, 8, 7, 15, 15 },
136  { 43, 43, 8, 8, 8, 8, 15, 15 },
137  { 43, 43, 8, 8, 8, 8, 15, 15 },
138  { 43, 43, 8, 8, 8, 8, 15, 15 },
139  { 43, 43, 8, 8, 8, 8, 15, 15 },
140  { 43, 43, 8, 8, 8, 8, 15, 15 },
141  { 43, 43, 8, 8, 8, 8, 15, 15 },
142  { 43, 43, 8, 8, 8, 8, 15, 15 },
143  { 43, 43, 8, 8, 8, 8, 15, 15 },
144  { 43, 43, 8, 8, 8, 8, 15, 15 },
145  { 43, 43, 8, 8, 8, 8, 15, 15 },
146  }
147 };
148 static void lookup_and_write(const int a1step,
149  const int row, const int col,
150  unsigned int mchbar)
151 {
152  int i;
153 
154  /* Write 4 32-bit registers, 4 values each. */
155  for (i = row; i < row + 16; i += 4) {
156  mchbar_write32(mchbar,
157  (ddr3_lut[a1step][i + 0][col] & 0x3f) << 0 |
158  (ddr3_lut[a1step][i + 1][col] & 0x3f) << 8 |
159  (ddr3_lut[a1step][i + 2][col] & 0x3f) << 16 |
160  (ddr3_lut[a1step][i + 3][col] & 0x3f) << 24);
161  mchbar += 4;
162  }
163 }
165  const int a1step = stepping >= STEPPING_CONVERSION_A1;
166 
167  int i;
168 
169  enum {
170  PULL_UP = 0,
171  PULL_DOWN = 1,
172  };
173  /* channel X group X pull-up/-down */
174  char lut_idx[2][6][2];
175  for (i = 0; i < 2 * 6 * 2; ++i)
176  ((char *)lut_idx)[i] = -1;
177 
178  mchbar_setbits32(0x400, 1 << 2);
179  mchbar_setbits32(0x418, 1 << 17);
180  mchbar_clrbits32(0x40c, 1 << 23);
181  mchbar_clrbits32(0x41c, 1 << 7 | 1 << 3);
182  mchbar_setbits32(0x400, 1 << 0);
183 
184  /* Read lookup indices. */
185  for (i = 0; i < 12; ++i) {
186  do {
187  mchbar_setbits32(0x400, 1 << 3);
188  udelay(10);
189  mchbar_clrbits32(0x400, 1 << 3);
190  } while ((mchbar_read32(0x530) & 0x7) != 0x4);
191  u32 reg = mchbar_read32(0x400);
192  const unsigned int group = (reg >> 13) & 0x7;
193  const unsigned int channel = (reg >> 12) & 0x1;
194  if (group > 5)
195  break;
196  reg = mchbar_read32(0x518);
197  lut_idx[channel][group][PULL_UP] = (reg >> 24) & 0x7f;
198  lut_idx[channel][group][PULL_DOWN] = (reg >> 16) & 0x7f;
199  }
200  /* Cleanup? */
201  mchbar_setbits32(0x400, 1 << 3);
202  udelay(10);
203  mchbar_clrbits32(0x400, 1 << 3);
204  mchbar_clrbits32(0x400, 1 << 2);
205 
206  /* Check for consistency. */
207  for (i = 0; i < 2 * 6 * 2; ++i) {
208  const char idx = ((char *)lut_idx)[i];
209  if ((idx < 7) || (idx > 55))
210  die("Bad RCOMP calibration lookup index.\n");
211  }
212 
213  /* Lookup values and fill registers. */
214  int channel, group, pu_pd;
215  unsigned int mchbar = 0x0680;
216  for (channel = 0; channel < 2; ++channel) {
217  for (group = 0; group < 6; ++group) {
218  for (pu_pd = PULL_DOWN; pu_pd >= PULL_UP; --pu_pd) {
220  a1step,
221  lut_idx[channel][group][pu_pd] - 7,
222  ddr3_lookup_schedule[group][pu_pd],
223  mchbar);
224  mchbar += 0x0018;
225  }
226  mchbar += 0x0010;
227  /* Channel B knows only the first two groups. */
228  if ((1 == channel) && (1 == group))
229  break;
230  }
231  mchbar += 0x0040;
232  }
233 }
void __noreturn die(const char *fmt,...)
Definition: die.c:17
#define mchbar_setbits32(addr, set)
Definition: fixed_bars.h:58
static __always_inline void mchbar_write32(const uintptr_t offset, const uint32_t value)
Definition: fixed_bars.h:36
static __always_inline uint32_t mchbar_read32(const uintptr_t offset)
Definition: fixed_bars.h:21
#define mchbar_clrbits32(addr, clear)
Definition: fixed_bars.h:62
stepping_t
Definition: gm45.h:14
@ STEPPING_CONVERSION_A1
Definition: gm45.h:25
#define PULL_DOWN
Definition: buildOpts.c:71
#define PULL_UP
Definition: buildOpts.c:70
static void lookup_and_write(const int a1step, const int row, const int col, unsigned int mchbar)
static const int ddr3_lookup_schedule[6][2]
void raminit_rcomp_calibration(const stepping_t stepping)
static const u8 ddr3_lut[2][64][8]
const char * stepping
uint32_t u32
Definition: stdint.h:51
uint8_t u8
Definition: stdint.h:45
void udelay(uint32_t us)
Definition: udelay.c:15