blob: f3b910f8142ce0a2fd15e2b6ff83a699a827a3b2 [file] [log] [blame]
Damien Zammit43a1f782015-08-19 15:16:59 +10001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2008 coresystems GmbH
5 * 2012 secunet Security Networks AG
6 * Copyright (C) 2015 Damien Zammit <damien@zamaudio.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#ifndef __NORTHBRIDGE_INTEL_X4X_H__
19#define __NORTHBRIDGE_INTEL_X4X_H__
20
Damien Zammit43a1f782015-08-19 15:16:59 +100021/*
22 * D0:F0
23 */
24#define D0F0_EPBAR_LO 0x40
25#define D0F0_EPBAR_HI 0x44
26#define D0F0_MCHBAR_LO 0x48
27#define D0F0_MCHBAR_HI 0x4c
28#define D0F0_GGC 0x52
29#define D0F0_DEVEN 0x54
Damien Zammitfe9876a2016-01-22 19:11:05 +110030#define D0EN (1 << 0)
31#define D1EN (1 << 1)
32#define IGD0EN (1 << 3)
33#define IGD1EN (1 << 4)
34#define D3F0EN (1 << 6)
35#define D3F1EN (1 << 7)
36#define D3F2EN (1 << 8)
37#define D3F3EN (1 << 9)
38#define PEG1EN (1 << 13)
Damien Zammita99c64e2016-09-05 02:36:02 +100039#define BOARD_DEVEN (D0EN | D1EN | IGD0EN | IGD1EN | PEG1EN)
Damien Zammit43a1f782015-08-19 15:16:59 +100040#define D0F0_PCIEXBAR_LO 0x60
41#define D0F0_PCIEXBAR_HI 0x64
42#define D0F0_DMIBAR_LO 0x68
43#define D0F0_DMIBAR_HI 0x6c
Damien Zammit43a1f782015-08-19 15:16:59 +100044#define D0F0_PAM(x) (0x90+(x)) /* 0-6*/
45#define D0F0_REMAPBASE 0x98
46#define D0F0_REMAPLIMIT 0x9a
47#define D0F0_SMRAM 0x9d
48#define D0F0_ESMRAMC 0x9e
49#define D0F0_TOM 0xa0
50#define D0F0_TOUUD 0xa2
51#define D0F0_TOLUD 0xb0
52#define D0F0_GBSM 0xa4
53#define D0F0_BGSM 0xa8
54#define D0F0_TSEG 0xac
55#define D0F0_SKPD 0xdc /* Scratchpad Data */
56#define D0F0_CAPID0 0xe0
57
58/*
59 * D1:F0 PEG
60 */
61#define PEG_CAP 0xa2
62#define SLOTCAP 0xb4
63#define PEGLC 0xec
64#define D1F0_VCCAP 0x104
65#define D1F0_VC0RCTL 0x114
66
67/*
68 * Graphics frequencies
69 */
70#define GCFGC_PCIDEV PCI_DEV(0, 2, 0)
71#define GCFGC_OFFSET 0xf0
72#define GCFGC_CR_SHIFT 0
73#define GCFGC_CR_MASK (0xf << GCFGC_CR_SHIFT)
74#define GCFGC_CS_SHIFT 8
75#define GCFGC_CS_MASK (0xf << GCFGC_CS_SHIFT)
76#define GCFGC_CD_SHIFT 12
77#define GCFGC_CD_MASK (0x1 << GCFGC_CD_SHIFT)
78#define GCFGC_UPDATE_SHIFT 5
79#define GCFGC_UPDATE (0x1 << GCFGC_UPDATE_SHIFT)
80
81/*
82 * MCHBAR
83 */
84
Arthur Heymans70a1dda2017-03-09 01:58:24 +010085#define MCHBAR8(x) (*((volatile u8 *)(DEFAULT_MCHBAR + (x))))
86#define MCHBAR16(x) (*((volatile u16 *)(DEFAULT_MCHBAR + (x))))
87#define MCHBAR32(x) (*((volatile u32 *)(DEFAULT_MCHBAR + (x))))
Damien Zammit43a1f782015-08-19 15:16:59 +100088
Arthur Heymans1994e4482017-11-04 07:52:23 +010089#define CHDECMISC 0x111
90#define STACKED_MEM (1 << 1)
91
92#define C0DRB0 0x200
93#define C0DRB1 0x202
94#define C0DRB2 0x204
95#define C0DRB3 0x206
96#define C0DRA01 0x208
97#define C0DRA23 0x20a
98#define C0CKECTRL 0x260
99
100#define C1DRB0 0x600
101#define C1DRB1 0x602
102#define C1DRB2 0x604
103#define C1DRB3 0x606
104#define C1DRA01 0x608
105#define C1DRA23 0x60a
106#define C1CKECTRL 0x660
107
Damien Zammit43a1f782015-08-19 15:16:59 +1000108#define PMSTS_MCHBAR 0x0f14 /* Self refresh channel status */
Arthur Heymans97e13d82016-11-30 18:40:38 +0100109#define PMSTS_WARM_RESET (1 << 8)
110#define PMSTS_BOTH_SELFREFRESH (3 << 0)
Damien Zammit43a1f782015-08-19 15:16:59 +1000111
112#define CLKCFG_MCHBAR 0x0c00
113#define CLKCFG_FSBCLK_SHIFT 0
114#define CLKCFG_FSBCLK_MASK (7 << CLKCFG_FSBCLK_SHIFT)
115#define CLKCFG_MEMCLK_SHIFT 4
116#define CLKCFG_MEMCLK_MASK (7 << CLKCFG_MEMCLK_SHIFT)
117#define CLKCFG_UPDATE (1 << 12)
118
Arthur Heymans5b30b822016-12-01 18:41:50 +0100119#define SSKPD_MCHBAR 0x0c20 /* 64 bit */
Damien Zammit43a1f782015-08-19 15:16:59 +1000120
121/*
122 * DMIBAR
123 */
124
Arthur Heymans70a1dda2017-03-09 01:58:24 +0100125#define DMIBAR8(x) (*((volatile u8 *)(DEFAULT_DMIBAR + (x))))
126#define DMIBAR16(x) (*((volatile u16 *)(DEFAULT_DMIBAR + (x))))
127#define DMIBAR32(x) (*((volatile u32 *)(DEFAULT_DMIBAR + (x))))
Damien Zammit43a1f782015-08-19 15:16:59 +1000128
129#define DMIVC0RCTL 0x14
130#define DMIVC1RCTL 0x20
131#define DMIVC1RSTS 0x26
132#define DMIESD 0x44
133#define DMILE1D 0x50
134#define DMILE1A 0x58
135#define DMILE2D 0x60
136#define DMILE2A 0x68
137
138/*
139 * EPBAR
140 */
141
Arthur Heymans70a1dda2017-03-09 01:58:24 +0100142#define EPBAR8(x) (*((volatile u8 *)(DEFAULT_EPBAR + (x))))
143#define EPBAR16(x) (*((volatile u16 *)(DEFAULT_EPBAR + (x))))
144#define EPBAR32(x) (*((volatile u32 *)(DEFAULT_EPBAR + (x))))
Damien Zammit43a1f782015-08-19 15:16:59 +1000145
146#define EPESD 0x44
147#define EPLE1D 0x50
148#define EPLE1A 0x58
149#define EPLE2D 0x60
150
151#define NOP_CMD 0x2
152#define PRECHARGE_CMD 0x4
153#define MRS_CMD 0x6
154#define EMRS_CMD 0x8
155#define EMRS1_CMD (EMRS_CMD | 0x10)
156#define EMRS2_CMD (EMRS_CMD | 0x20)
157#define EMRS3_CMD (EMRS_CMD | 0x30)
158#define ZQCAL_CMD 0xa
159#define CBR_CMD 0xc
160#define NORMALOP_CMD 0xe
161
162#define TOTAL_CHANNELS 2
163#define TOTAL_DIMMS 4
Arthur Heymans276049f2017-11-05 05:56:34 +0100164#define TOTAL_BYTELANES 8
Nico Huber3c209062016-11-26 02:03:25 +0100165#define DIMMS_PER_CHANNEL (TOTAL_DIMMS / TOTAL_CHANNELS)
Damien Zammit68e1dcf2016-06-03 15:39:30 +1000166#define RAW_CARD_UNPOPULATED 0xff
Arthur Heymans3cf94032017-04-05 16:17:26 +0200167#define RAW_CARD_POPULATED 0
Damien Zammit43a1f782015-08-19 15:16:59 +1000168
Damien Zammit68e1dcf2016-06-03 15:39:30 +1000169#define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != RAW_CARD_UNPOPULATED)
170#define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != RAW_CARD_UNPOPULATED)
Damien Zammit43a1f782015-08-19 15:16:59 +1000171#define ONLY_DIMMA_IS_POPULATED(dimms, ch) ( \
172 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
173 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3)))
174#define ONLY_DIMMB_IS_POPULATED(dimms, ch) ( \
175 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3) && \
176 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2)))
177#define BOTH_DIMMS_ARE_POPULATED(dimms, ch) ( \
178 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
179 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3))))
180#define FOR_EACH_DIMM(idx) \
181 for (idx = 0; idx < TOTAL_DIMMS; ++idx)
182#define FOR_EACH_POPULATED_DIMM(dimms, idx) \
183 FOR_EACH_DIMM(idx) IF_DIMM_POPULATED(dimms, idx)
Nico Huber696abfc2016-11-23 23:56:53 +0100184#define FOR_EACH_DIMM_IN_CHANNEL(ch, idx) \
Nico Huber3c209062016-11-26 02:03:25 +0100185 for (idx = (ch) << 1; idx < ((ch) << 1) + DIMMS_PER_CHANNEL; ++idx)
Nico Huber696abfc2016-11-23 23:56:53 +0100186#define FOR_EACH_POPULATED_DIMM_IN_CHANNEL(dimms, ch, idx) \
187 FOR_EACH_DIMM_IN_CHANNEL(ch, idx) IF_DIMM_POPULATED(dimms, idx)
Arthur Heymans70a1dda2017-03-09 01:58:24 +0100188#define CHANNEL_IS_POPULATED(dimms, idx) \
189 ((dimms[idx<<1].card_type != RAW_CARD_UNPOPULATED) \
190 || (dimms[(idx<<1) + 1].card_type != RAW_CARD_UNPOPULATED))
191#define CHANNEL_IS_CARDF(dimms, idx) \
192 ((dimms[idx<<1].card_type == 0xf) \
193 || (dimms[(idx<<1) + 1].card_type == 0xf))
194#define IF_CHANNEL_POPULATED(dimms, idx) \
195 if ((dimms[idx<<1].card_type != RAW_CARD_UNPOPULATED) \
196 || (dimms[(idx<<1) + 1].card_type != RAW_CARD_UNPOPULATED))
Damien Zammit43a1f782015-08-19 15:16:59 +1000197#define FOR_EACH_CHANNEL(idx) \
198 for (idx = 0; idx < TOTAL_CHANNELS; ++idx)
199#define FOR_EACH_POPULATED_CHANNEL(dimms, idx) \
200 FOR_EACH_CHANNEL(idx) IF_CHANNEL_POPULATED(dimms, idx)
201
202#define RANKS_PER_CHANNEL 4
203#define RANK_IS_POPULATED(dimms, ch, r) \
Damien Zammit68e1dcf2016-06-03 15:39:30 +1000204 (((dimms[ch<<1].card_type != RAW_CARD_UNPOPULATED) && ((r) < dimms[ch<<1].ranks)) || \
205 ((dimms[(ch<<1) + 1].card_type != RAW_CARD_UNPOPULATED) && ((r) >= 2) && ((r) < (dimms[(ch<<1) + 1].ranks + 2))))
Damien Zammit43a1f782015-08-19 15:16:59 +1000206#define IF_RANK_POPULATED(dimms, ch, r) \
Arthur Heymans70a1dda2017-03-09 01:58:24 +0100207 if (((dimms[ch<<1].card_type != RAW_CARD_UNPOPULATED) \
208 && ((r) < dimms[ch<<1].ranks)) \
209 || ((dimms[(ch<<1) + 1].card_type != RAW_CARD_UNPOPULATED) \
210 && ((r) >= 2) && ((r) < (dimms[(ch<<1) + 1].ranks + 2))))
Damien Zammit43a1f782015-08-19 15:16:59 +1000211#define FOR_EACH_RANK_IN_CHANNEL(r) \
212 for (r = 0; r < RANKS_PER_CHANNEL; ++r)
213#define FOR_EACH_POPULATED_RANK_IN_CHANNEL(dimms, ch, r) \
214 FOR_EACH_RANK_IN_CHANNEL(r) IF_RANK_POPULATED(dimms, ch, r)
215#define FOR_EACH_RANK(ch, r) \
216 FOR_EACH_CHANNEL(ch) FOR_EACH_RANK_IN_CHANNEL(r)
217#define FOR_EACH_POPULATED_RANK(dimms, ch, r) \
218 FOR_EACH_RANK(ch, r) IF_RANK_POPULATED(dimms, ch, r)
Arthur Heymans276049f2017-11-05 05:56:34 +0100219#define FOR_EACH_BYTELANE(l) \
220 for (l = 0; l < TOTAL_BYTELANES; l++)
221#define FOR_EACH_POPULATED_CHANNEL_AND_BYTELANE(dimms, ch, l) \
222 FOR_EACH_POPULATED_CHANNEL (dimms, ch) FOR_EACH_BYTELANE(l)
Damien Zammit43a1f782015-08-19 15:16:59 +1000223
224#define DDR3_MAX_CAS 18
225
226enum fsb_clock {
227 FSB_CLOCK_800MHz = 0,
228 FSB_CLOCK_1066MHz = 1,
229 FSB_CLOCK_1333MHz = 2,
230};
231
232enum mem_clock {
233 MEM_CLOCK_400MHz = 0,
234 MEM_CLOCK_533MHz = 1,
235 MEM_CLOCK_667MHz = 2,
236 MEM_CLOCK_800MHz = 3,
237 MEM_CLOCK_1066MHz = 4,
238 MEM_CLOCK_1333MHz = 5,
239};
240
241enum ddr {
242 DDR2 = 2,
243 DDR3 = 3,
244};
245
246enum ddrxspd {
247 DDR2SPD = 0x8,
248 DDR3SPD = 0xb,
249};
250
251enum chip_width { /* as in DDR3 spd */
252 CHIP_WIDTH_x4 = 0,
253 CHIP_WIDTH_x8 = 1,
254 CHIP_WIDTH_x16 = 2,
255 CHIP_WIDTH_x32 = 3,
256};
257
258enum chip_cap { /* as in DDR3 spd */
259 CHIP_CAP_256M = 0,
260 CHIP_CAP_512M = 1,
261 CHIP_CAP_1G = 2,
262 CHIP_CAP_2G = 3,
263 CHIP_CAP_4G = 4,
264 CHIP_CAP_8G = 5,
265 CHIP_CAP_16G = 6,
266};
267
Arthur Heymans27f0ca12017-05-09 18:38:14 +0200268struct dll_setting {
269 u8 tap;
270 u8 pi;
271 u8 db_en;
272 u8 db_sel;
273 u8 clk_delay;
274 u8 coarse;
275};
276
Arthur Heymans0bf87de2017-11-04 06:15:05 +0100277struct rt_dqs_setting {
278 u8 tap;
279 u8 pi;
280};
281
Arthur Heymans3cf94032017-04-05 16:17:26 +0200282enum n_banks {
283 N_BANKS_4 = 0,
284 N_BANKS_8 = 1,
285};
286
Damien Zammit43a1f782015-08-19 15:16:59 +1000287struct timings {
288 unsigned int CAS;
Arthur Heymans3cf94032017-04-05 16:17:26 +0200289 unsigned int tclk;
Damien Zammit43a1f782015-08-19 15:16:59 +1000290 enum fsb_clock fsb_clk;
291 enum mem_clock mem_clk;
292 unsigned int tRAS;
293 unsigned int tRP;
294 unsigned int tRCD;
295 unsigned int tWR;
296 unsigned int tRFC;
297 unsigned int tWTR;
298 unsigned int tRRD;
299 unsigned int tRTP;
300};
301
302struct dimminfo {
Damien Zammit68e1dcf2016-06-03 15:39:30 +1000303 unsigned int card_type; /* 0xff: unpopulated,
Damien Zammit43a1f782015-08-19 15:16:59 +1000304 0xa - 0xf: raw card type A - F */
305 enum chip_width width;
Damien Zammit43a1f782015-08-19 15:16:59 +1000306 unsigned int page_size; /* of whole DIMM in Bytes (4096 or 8192) */
Arthur Heymans3cf94032017-04-05 16:17:26 +0200307 enum n_banks n_banks;
Damien Zammit43a1f782015-08-19 15:16:59 +1000308 unsigned int ranks;
309 unsigned int rows;
310 unsigned int cols;
Arthur Heymansadc571a2017-09-25 09:40:54 +0200311 u16 spd_crc;
312};
313
314struct rcven_timings {
315 u8 min_common_coarse;
Arthur Heymans276049f2017-11-05 05:56:34 +0100316 u8 coarse_offset[TOTAL_BYTELANES];
317 u8 medium[TOTAL_BYTELANES];
318 u8 tap[TOTAL_BYTELANES];
319 u8 pi[TOTAL_BYTELANES];
Damien Zammit43a1f782015-08-19 15:16:59 +1000320};
321
322/* The setup is up to two DIMMs per channel */
323struct sysinfo {
Damien Zammit43a1f782015-08-19 15:16:59 +1000324 int boot_path;
Damien Zammit43a1f782015-08-19 15:16:59 +1000325 enum fsb_clock max_fsb;
Damien Zammit43a1f782015-08-19 15:16:59 +1000326
327 int dimm_config[2];
Damien Zammit43a1f782015-08-19 15:16:59 +1000328 int spd_type;
329 int channel_capacity[2];
330 struct timings selected_timings;
331 struct dimminfo dimms[4];
332 u8 spd_map[4];
Arthur Heymansadc571a2017-09-25 09:40:54 +0200333 struct rcven_timings rcven_t[TOTAL_CHANNELS];
Arthur Heymans0bf87de2017-11-04 06:15:05 +0100334 /*
335 * The rt_dqs delay register for rank 0 seems to be used
336 * for all other ranks on the channel, so only save that
337 */
Arthur Heymans276049f2017-11-05 05:56:34 +0100338 struct rt_dqs_setting rt_dqs[TOTAL_CHANNELS][TOTAL_BYTELANES];
339 struct dll_setting dqs_settings[TOTAL_CHANNELS][TOTAL_BYTELANES];
340 struct dll_setting dq_settings[TOTAL_CHANNELS][TOTAL_BYTELANES];
Damien Zammit43a1f782015-08-19 15:16:59 +1000341};
Arthur Heymans97e13d82016-11-30 18:40:38 +0100342#define BOOT_PATH_NORMAL 0
343#define BOOT_PATH_WARM_RESET 1
344#define BOOT_PATH_RESUME 2
Damien Zammit43a1f782015-08-19 15:16:59 +1000345
346enum ddr2_signals {
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200347 CLKSET0 = 0,
348 CTRL0,
349 CLKSET1,
350 CMD,
351 CTRL1,
352 CTRL2,
353 CTRL3,
Damien Zammit43a1f782015-08-19 15:16:59 +1000354};
355
Martin Rothcbe38922016-01-05 19:40:41 -0700356#ifndef __BOOTBLOCK__
Damien Zammit43a1f782015-08-19 15:16:59 +1000357void x4x_early_init(void);
Arthur Heymansef7e98a2016-12-30 21:07:18 +0100358void x4x_late_init(int s3resume);
Damien Zammit43a1f782015-08-19 15:16:59 +1000359u32 decode_igd_memory_size(u32 gms);
360u32 decode_igd_gtt_size(u32 gsm);
361u8 decode_pciebar(u32 *const base, u32 *const len);
362void sdram_initialize(int boot_path, const u8 *spd_map);
Arthur Heymansa2cc2312017-05-15 10:13:36 +0200363void do_raminit(struct sysinfo *, int fast_boot);
Arthur Heymansadc571a2017-09-25 09:40:54 +0200364void rcven(struct sysinfo *s);
Arthur Heymans3cf94032017-04-05 16:17:26 +0200365u32 fsb2mhz(u32 speed);
366u32 ddr2mhz(u32 speed);
Arthur Heymans1994e4482017-11-04 07:52:23 +0100367u32 test_address(int channel, int rank);
Arthur Heymans95c48cb2017-11-04 08:07:06 +0100368void dqsset(u8 ch, u8 lane, const struct dll_setting *setting);
369void dqset(u8 ch, u8 lane, const struct dll_setting *setting);
370void rt_set_dqs(u8 channel, u8 lane, u8 rank,
371 struct rt_dqs_setting *dqs_setting);
372int do_write_training(struct sysinfo *s);
373int do_read_training(struct sysinfo *s);
Damien Zammit43a1f782015-08-19 15:16:59 +1000374
Arthur Heymans0bf87de2017-11-04 06:15:05 +0100375extern const struct dll_setting default_ddr2_667_ctrl[7];
376extern const struct dll_setting default_ddr2_800_ctrl[7];
377extern const struct dll_setting default_ddr3_800_ctrl[2][7];
378extern const struct dll_setting default_ddr3_1067_ctrl[2][7];
379extern const struct dll_setting default_ddr3_1333_ctrl[2][7];
Arthur Heymans276049f2017-11-05 05:56:34 +0100380extern const struct dll_setting default_ddr2_667_dqs[TOTAL_BYTELANES];
381extern const struct dll_setting default_ddr2_800_dqs[TOTAL_BYTELANES];
382extern const struct dll_setting default_ddr3_800_dqs[2][TOTAL_BYTELANES];
383extern const struct dll_setting default_ddr3_1067_dqs[2][TOTAL_BYTELANES];
384extern const struct dll_setting default_ddr3_1333_dqs[2][TOTAL_BYTELANES];
385extern const struct dll_setting default_ddr2_667_dq[TOTAL_BYTELANES];
386extern const struct dll_setting default_ddr2_800_dq[TOTAL_BYTELANES];
387extern const struct dll_setting default_ddr3_800_dq[2][TOTAL_BYTELANES];
388extern const struct dll_setting default_ddr3_1067_dq[2][TOTAL_BYTELANES];
389extern const struct dll_setting default_ddr3_1333_dq[2][TOTAL_BYTELANES];
Arthur Heymans0bf87de2017-11-04 06:15:05 +0100390
Damien Zammit43a1f782015-08-19 15:16:59 +1000391struct acpi_rsdp;
Antonello Dettori60a6e152016-09-03 10:45:33 +0200392#ifndef __SIMPLE_DEVICE__
Elyes HAOUASfea02e12018-02-08 14:59:03 +0100393unsigned long northbridge_write_acpi_tables(struct device *device,
394 unsigned long start, struct acpi_rsdp *rsdp);
Antonello Dettori60a6e152016-09-03 10:45:33 +0200395#endif /* __SIMPLE_DEVICE__ */
Martin Rothcbe38922016-01-05 19:40:41 -0700396#endif
Damien Zammit43a1f782015-08-19 15:16:59 +1000397#endif /* __NORTHBRIDGE_INTEL_X4X_H__ */