nb/intel/ironlake: Split out some QuickPath init code
The platform performs a CPU-only reset after initializing QPI (QuickPath
Interconnect) and before actually performing raminit. The state is saved
in the sticky scratchpad register at MCHBAR + 0x2ca8.
Relocate some QuickPath init to a separate file. All moved functions are
only used within QPI init code, and had to be relocated in one commit.
Tested on out-of-tree HP 630, still boots.
Change-Id: I48e3517285d8fd4b448add131cd8bfb80641e7ef
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/49582
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/northbridge/intel/ironlake/raminit.h b/src/northbridge/intel/ironlake/raminit.h
index 5bb2f59..9967e15 100644
--- a/src/northbridge/intel/ironlake/raminit.h
+++ b/src/northbridge/intel/ironlake/raminit.h
@@ -5,6 +5,93 @@
#include "ironlake.h"
+#define NUM_CHANNELS 2
+#define NUM_SLOTS 2
+#define NUM_RANKS 2
+
+/* [REG_178][CHANNEL][2 * SLOT + RANK][LANE] */
+typedef struct {
+ u8 smallest;
+ u8 largest;
+} timing_bounds_t[2][2][2][9];
+
+#define MRC_CACHE_VERSION 3
+
+struct ram_training {
+ /* [TM][CHANNEL][SLOT][RANK][LANE] */
+ u16 lane_timings[4][2][2][2][9];
+ u16 reg_178;
+ u16 reg_10b;
+
+ u8 reg178_center;
+ u8 reg178_smallest;
+ u8 reg178_largest;
+ timing_bounds_t timing_bounds[2];
+ u16 timing_offset[2][2][2][9];
+ u16 timing2_offset[2][2][2][9];
+ u16 timing2_bounds[2][2][2][9][2];
+ u8 reg274265[2][3]; /* [CHANNEL][REGISTER] */
+ u8 reg2ca9_bit0;
+ u32 reg_6dc;
+ u32 reg_6e8;
+};
+
+struct raminfo {
+ u16 clock_speed_index; /* clock_speed (REAL, not DDR) / 133.(3) - 3 */
+ u16 fsb_frequency; /* in 1.(1)/2 MHz. */
+ u8 is_x16_module[2][2]; /* [CHANNEL][SLOT] */
+ u8 density[2][2]; /* [CHANNEL][SLOT] */
+ u8 populated_ranks[2][2][2]; /* [CHANNEL][SLOT][RANK] */
+ int rank_start[2][2][2];
+ u8 cas_latency;
+ u8 board_lane_delay[9];
+ u8 use_ecc;
+ u8 revision;
+ u8 max_supported_clock_speed_index;
+ u8 uma_enabled;
+ u8 spd[2][2][151]; /* [CHANNEL][SLOT][BYTE] */
+ u8 silicon_revision;
+ u8 populated_ranks_mask[2];
+ u8 max_slots_used_in_channel;
+ u8 mode4030[2];
+ u16 avg4044[2];
+ u16 max4048[2];
+ unsigned int total_memory_mb;
+ unsigned int interleaved_part_mb;
+ unsigned int non_interleaved_part_mb;
+
+ unsigned int memory_reserved_for_heci_mb;
+
+ struct ram_training training;
+ u32 last_500_command[2];
+
+ u32 delay46_ps[2];
+ u32 delay54_ps[2];
+ u8 revision_flag_1;
+ u8 some_delay_1_cycle_floor;
+ u8 some_delay_2_halfcycles_ceil;
+ u8 some_delay_3_ps_rounded;
+
+ const struct ram_training *cached_training;
+};
+
+static inline unsigned int fsbcycle_ps(struct raminfo *info)
+{
+ return 900000 / info->fsb_frequency;
+}
+
+/* The time of DDR transfer in ps. */
+static inline unsigned int halfcycle_ps(struct raminfo *info)
+{
+ return 3750 / (info->clock_speed_index + 3);
+}
+
+/* Frequency in 1.(1)=10/9 MHz units. */
+static inline unsigned int frequency_11(struct raminfo *info)
+{
+ return (info->clock_speed_index + 3) * 120;
+}
+
void chipset_init(const int s3resume);
/* spd_addrmap is array of 4 elements:
Channel 0 Slot 0
@@ -15,4 +102,7 @@
*/
void raminit(const int s3resume, const u8 *spd_addrmap);
+u16 get_max_timing(struct raminfo *info, int channel);
+void late_quickpath_init(struct raminfo *info, const int s3resume);
+
#endif /* RAMINIT_H */