soc/mediatek/mt8196: Initialize SSPM
[coreboot2.git] / src / mainboard / google / cyan / spd / spd.c
blobbd08b8257c806f51ba241db9f8d7966efd882c9a
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <cbfs.h>
4 #include <cbmem.h>
5 #include <console/console.h>
6 #include <gpio.h>
7 #include <lib.h>
8 #include <memory_info.h>
9 #include <smbios.h>
10 #include <spd.h>
11 #include <soc/romstage.h>
12 #include <string.h>
13 #include <spd_bin.h>
14 #include "spd_util.h"
16 __weak uint8_t get_ramid(void)
18 gpio_t spd_gpios[] = {
19 GP_SW_80, /* SATA_GP3, RAMID0 */
20 GP_SW_67, /* I2C3_SCL, RAMID1 */
21 GP_SE_02, /* MF_PLT_CLK1, RAMID2 */
22 GP_SW_64, /* I2C3_SDA, RAMID3 */
25 return gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios));
28 static void *get_spd_pointer(int *dual)
30 char *spd_file;
31 size_t spd_file_len;
32 int total_spds;
33 int ram_id = 0;
34 int spd_index = 0;
36 /* Find the SPD data in CBFS. */
37 spd_file = cbfs_map("spd.bin", &spd_file_len);
38 if (!spd_file)
39 die("SPD data not found.");
41 if (spd_file_len < SPD_PAGE_LEN)
42 die("Missing SPD data.");
43 total_spds = spd_file_len / SPD_PAGE_LEN;
45 ram_id = get_ramid();
46 printk(BIOS_DEBUG, "ram_id=%d, total_spds: %d\n", ram_id, total_spds);
48 spd_index = get_variant_spd_index(ram_id, dual);
49 if (spd_index >= total_spds) {
50 printk(BIOS_ERR, "SPD index > total SPDs\n");
51 return NULL;
53 /* Return the serial product data for the RAM */
54 return &spd_file[SPD_PAGE_LEN * spd_index];
57 /* Copy SPD data for on-board memory */
58 void spd_memory_init_params(MEMORY_INIT_UPD *memory_params)
60 void *spd_content;
61 int dual_channel = 0;
64 * Both channels are always present in SPD data. Always use matched
65 * DIMMs so use the same SPD data for each DIMM.
67 spd_content = get_spd_pointer(&dual_channel);
68 if (CONFIG(DISPLAY_SPD_DATA) && spd_content != NULL) {
69 printk(BIOS_DEBUG, "SPD Data:\n");
70 hexdump(spd_content, SPD_PAGE_LEN);
71 printk(BIOS_DEBUG, "\n");
75 * Set SPD and memory configuration:
76 * Memory type: 0=DimmInstalled,
77 * 1=SolderDownMemory,
78 * 2=DimmDisabled
80 if (spd_content != NULL) {
81 memory_params->PcdMemChannel0Config = 1;
82 printk(BIOS_DEBUG, "Channel 0 DIMM soldered down\n");
83 if (dual_channel) {
84 printk(BIOS_DEBUG, "Channel 1 DIMM soldered down\n");
85 memory_params->PcdMemChannel1Config = 1;
86 } else {
87 printk(BIOS_DEBUG, "Channel 1 DIMM not installed\n");
88 memory_params->PcdMemChannel1Config = 2;
92 /* Update SPD data */
93 if (CONFIG(BOARD_GOOGLE_CYAN)) {
94 memory_params->PcdMemoryTypeEnable = MEM_DDR3;
95 memory_params->PcdMemorySpdPtr = (uintptr_t)spd_content;
96 } else {
97 memory_params->PcdMemoryTypeEnable = MEM_LPDDR3;
101 static void set_dimm_info(const uint8_t *spd, struct dimm_info *dimm)
103 const int spd_capmb[8] = { 1, 2, 4, 8, 16, 32, 64, 0 };
104 const int spd_ranks[8] = { 1, 2, 3, 4, -1, -1, -1, -1 };
105 const int spd_devw[8] = { 4, 8, 16, 32, -1, -1, -1, -1 };
106 const int spd_busw[8] = { 8, 16, 32, 64, -1, -1, -1, -1 };
108 int capmb = spd_capmb[spd[SPD_DENSITY_BANKS] & 7] * 256;
109 int ranks = spd_ranks[(spd[DDR3_ORGANIZATION] >> 3) & 7];
110 int devw = spd_devw[spd[DDR3_ORGANIZATION] & 7];
111 int busw = spd_busw[spd[DDR3_BUS_DEV_WIDTH] & 7];
113 void *hob_list_ptr;
114 EFI_HOB_GUID_TYPE *hob_ptr;
115 FSP_SMBIOS_MEMORY_INFO *memory_info_hob;
116 const EFI_GUID memory_info_hob_guid = FSP_SMBIOS_MEMORY_INFO_GUID;
118 /* Locate the memory info HOB, presence validated by raminit */
119 hob_list_ptr = fsp_get_hob_list();
120 hob_ptr = get_guid_hob(&memory_info_hob_guid, hob_list_ptr);
121 if (hob_ptr != NULL) {
122 memory_info_hob = (FSP_SMBIOS_MEMORY_INFO *)(hob_ptr + 1);
123 dimm->ddr_frequency = memory_info_hob->MemoryFrequencyInMHz;
124 } else {
125 printk(BIOS_ERR, "Can't get memory info hob pointer\n");
126 dimm->ddr_frequency = 0;
129 /* Parse the SPD data to determine the DIMM information */
130 if (CONFIG(BOARD_GOOGLE_CYAN)) {
131 dimm->ddr_type = MEMORY_TYPE_DDR3;
132 } else {
133 dimm->ddr_type = MEMORY_TYPE_LPDDR3;
135 dimm->dimm_size = capmb / 8 * busw / devw * ranks; /* MiB */
136 dimm->mod_type = spd[3] & 0xf;
137 strncpy((char *)&dimm->module_part_number[0], (char *)&spd[0x80],
138 LPDDR3_SPD_PART_LEN);
139 dimm->module_part_number[LPDDR3_SPD_PART_LEN] = 0;
140 dimm->mod_id = *(uint16_t *)&spd[0x94];
142 switch (busw) {
143 default:
144 case 8:
145 dimm->bus_width = MEMORY_BUS_WIDTH_8;
146 break;
148 case 16:
149 dimm->bus_width = MEMORY_BUS_WIDTH_16;
150 break;
152 case 32:
153 dimm->bus_width = MEMORY_BUS_WIDTH_32;
154 break;
156 case 64:
157 dimm->bus_width = MEMORY_BUS_WIDTH_64;
158 break;
162 void mainboard_save_dimm_info(struct romstage_params *params)
164 const void *spd_content;
165 int dual_channel;
166 struct dimm_info *dimm;
167 struct memory_info *mem_info;
169 spd_content = get_spd_pointer(&dual_channel);
170 if (spd_content == NULL)
171 return;
174 * Allocate CBMEM area for DIMM information used to populate SMBIOS
175 * table 17
177 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
178 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: %p\n", mem_info);
179 if (mem_info == NULL)
180 return;
181 memset(mem_info, 0, sizeof(*mem_info));
183 /* Describe the first channel memory */
184 dimm = &mem_info->dimm[0];
185 set_dimm_info(spd_content, dimm);
186 mem_info->dimm_cnt = 1;
188 /* Describe the second channel memory */
189 if (dual_channel) {
190 dimm = &mem_info->dimm[1];
191 set_dimm_info(spd_content, dimm);
192 dimm->channel_num = 1;
193 mem_info->dimm_cnt = 2;