coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
meminit.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/console.h>
5 #include <fsp/util.h>
6 #include <soc/meminit.h>
7 #include <spd_bin.h>
8 #include <string.h>
9 
10 static void spd_read_from_cbfs(const struct spd_info *spd_info, uintptr_t *spd_data_ptr,
11  size_t *spd_data_len)
12 {
14 
15  printk(BIOS_DEBUG, "SPD INDEX = %zu\n", spd_index);
16 
17  /* Memory leak is ok since we have memory mapped boot media */
18  assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
19 
20  *spd_data_len = CONFIG_DIMM_SPD_SIZE;
21  *spd_data_ptr = spd_cbfs_map(spd_index);
22  if (!*spd_data_ptr)
23  die("spd.bin not found or incorrect index\n");
24 }
25 
26 static void get_spd_data(const struct spd_info *spd_info, uintptr_t *spd_data_ptr,
27  size_t *spd_data_len)
28 {
32  return;
33  }
34 
36  spd_read_from_cbfs(spd_info, spd_data_ptr, spd_data_len);
37  return;
38  }
39 
40  die("no valid way to read SPD info");
41 }
42 
43 static void meminit_dq_dqs_map(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
44  bool half_populated)
45 {
46  memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor,
47  sizeof(mem_cfg->RcompResistor));
48 
49  memcpy(&mem_cfg->RcompTarget, &board_cfg->rcomp_targets,
50  sizeof(mem_cfg->RcompTarget));
51 
52  memcpy(&mem_cfg->DqByteMapCh0, &board_cfg->dq_map[DDR_CH0],
53  sizeof(board_cfg->dq_map[DDR_CH0]));
54 
55  memcpy(&mem_cfg->DqsMapCpu2DramCh0, &board_cfg->dqs_map[DDR_CH0],
56  sizeof(board_cfg->dqs_map[DDR_CH0]));
57 
58  if (half_populated)
59  return;
60 
61  memcpy(&mem_cfg->DqByteMapCh1, &board_cfg->dq_map[DDR_CH1],
62  sizeof(board_cfg->dq_map[DDR_CH1]));
63 
64  memcpy(&mem_cfg->DqsMapCpu2DramCh1, &board_cfg->dqs_map[DDR_CH1],
65  sizeof(board_cfg->dqs_map[DDR_CH1]));
66 }
67 
68 static void meminit_channels(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
69  uintptr_t spd_data_ptr, bool half_populated)
70 {
71  /* Channel 0 */
72  mem_cfg->MemorySpdPtr00 = spd_data_ptr;
73  mem_cfg->MemorySpdPtr01 = 0;
74 
75  if (half_populated) {
76  printk(BIOS_INFO, "%s: DRAM half-populated\n", __func__);
77  spd_data_ptr = 0;
78  }
79 
80  /* Channel 1 */
81  mem_cfg->MemorySpdPtr10 = spd_data_ptr;
82  mem_cfg->MemorySpdPtr11 = 0;
83 
84  meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated);
85 }
86 
87 /* Initialize onboard memory configurations for lpddr4x */
88 void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
89  const struct spd_info *spd_info, bool half_populated)
90 {
91 
92  if (spd_info->read_type == READ_SMBUS) {
93  for (int i = 0; i < NUM_DIMM_SLOT; i++)
94  mem_cfg->SpdAddressTable[i] = spd_info->spd_spec.spd_smbus_address[i];
95 
96  meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated);
97  } else {
98  uintptr_t spd_data_ptr = 0;
99  size_t spd_data_len = 0;
100  memset(&mem_cfg->SpdAddressTable, 0, sizeof(mem_cfg->SpdAddressTable));
101  get_spd_data(spd_info, &spd_data_ptr, &spd_data_len);
102  print_spd_info((unsigned char *)spd_data_ptr);
103 
104  mem_cfg->MemorySpdDataLen = spd_data_len;
105  meminit_channels(mem_cfg, board_cfg, spd_data_ptr, half_populated);
106  }
107 
108  /* Early Command Training Enabled */
109  mem_cfg->ECT = board_cfg->ect;
110 
111  mem_cfg->UserBd = board_cfg->UserBd;
112 }
void memcfg_init(FSPM_UPD *memupd, const struct mb_cfg *mb_cfg, const struct mem_spd *spd_info, bool half_populated)
Definition: meminit.c:238
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
#define assert(statement)
Definition: assert.h:74
@ READ_SPD_MEMPTR
@ READ_SMBUS
@ READ_SPD_CBFS
@ DDR_CH0
@ DDR_CH1
#define NUM_DIMM_SLOT
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
@ CONFIG
Definition: dsi_common.h:201
#define FSP_M_CONFIG
Definition: fsp_upd.h:8
static void meminit_dq_dqs_map(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg, bool half_populated)
Definition: meminit.c:43
static void meminit_channels(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg, uintptr_t spd_data_ptr, bool half_populated)
Definition: meminit.c:68
static void spd_read_from_cbfs(const struct spd_info *spd_info, uintptr_t *spd_data_ptr, size_t *spd_data_len)
Definition: meminit.c:10
static void get_spd_data(const struct spd_info *spd_info, uintptr_t *spd_data_ptr, size_t *spd_data_len)
Definition: meminit.c:26
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
static const int spd_index[32]
Definition: memory.c:10
static const struct mb_cfg board_cfg
Definition: romstage.c:8
uintptr_t spd_cbfs_map(u8 spd_index)
Definition: spd_bin.c:217
void print_spd_info(uint8_t spd[])
Definition: spd_bin.c:183
unsigned long uintptr_t
Definition: stdint.h:21
Definition: meminit.h:71
uint16_t rcomp_targets[5]
Definition: meminit.h:93
bool ect
Definition: meminit.h:100
uint8_t dqs_map[CONFIG_DATA_BUS_WIDTH/BITS_PER_BYTE]
Definition: meminit.h:90
uint8_t UserBd
Definition: meminit.h:103
uint16_t rcomp_resistor[3]
Definition: meminit.h:87
uint8_t dq_map[CONFIG_DATA_BUS_WIDTH]
Definition: meminit.h:80
uintptr_t spd_data_ptr
Definition: spd.h:11
union spd_info::spd_data_by spd_spec
enum mem_info_read_type read_type
struct spd_by_pointer spd_data_ptr_info