1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <acpi/acpigen.h>
7 #include <console/console.h>
10 #include <device/device.h>
11 #include <device/dram/spd.h>
12 #include <device/pci_ids.h>
13 #include <drivers/intel/gma/opregion.h>
15 #include <intelblocks/gpio.h>
16 #include <intelblocks/pmclib.h>
26 const char *mainboard_vbt_filename(void)
28 const struct eeprom_bmc_settings
*bmc_cfg
= get_bmc_settings();
30 if (bmc_cfg
&& bmc_cfg
->efp3_displayport
)
31 return "vbt-avalanche.bin";
33 return "vbt.bin"; /* Poseidon */
36 /* FIXME: Example code below */
38 static void mb_configure_dp1_pwr(bool enable
)
40 gpio_output(GPP_K3
, enable
);
43 static void mb_configure_dp2_pwr(bool enable
)
45 gpio_output(GPP_K4
, enable
);
48 static void mb_configure_dp3_pwr(bool enable
)
50 gpio_output(GPP_K5
, enable
);
53 static void mb_hda_amp_enable(bool enable
)
55 gpio_output(GPP_C19
, enable
);
58 static void mb_usb31_rp1_pwr_enable(bool enable
)
60 gpio_output(GPP_G0
, enable
);
63 static void mb_usb31_rp2_pwr_enable(bool enable
)
65 gpio_output(GPP_G1
, enable
);
68 static void mb_usb31_fp_pwr_enable(bool enable
)
70 gpio_output(GPP_G2
, enable
);
73 static void mb_usb2_fp1_pwr_enable(bool enable
)
75 gpio_output(GPP_G3
, enable
);
78 static void mb_usb2_fp2_pwr_enable(bool enable
)
80 gpio_output(GPP_G4
, enable
);
83 static void copy_meminfo(const struct dimm_info
*dimm
, union eeprom_dimm_layout
*l
)
85 memset(l
, 0, sizeof(*l
));
86 if (dimm
->dimm_size
== 0)
89 strncpy(l
->name
, (char *)dimm
->module_part_number
, sizeof(l
->name
) - 1);
90 l
->capacity_mib
= dimm
->dimm_size
;
91 l
->data_width_bits
= 8 * (1 << (dimm
->bus_width
& 0x7));
92 l
->bus_width_bits
= l
->data_width_bits
+ 8 * ((dimm
->bus_width
>> 3) & 0x3);
93 l
->ranks
= dimm
->rank_per_dimm
;
95 strncpy(l
->manufacturer
, spd_manufacturer_name(dimm
->mod_id
),
96 sizeof(l
->manufacturer
) - 1);
100 * Collect board specific settings and update the CFG EEPROM if necessary.
101 * This allows the BMC webui to display the current hardware configuration.
103 static void update_board_layout(void)
105 struct eeprom_board_layout layout
= {0};
107 printk(BIOS_INFO
, "MB: Collecting Board Layout information\n");
109 /* Update CPU fields */
110 for (struct device
*cpu
= all_devices
; cpu
; cpu
= cpu
->next
) {
111 if (!is_enabled_cpu(cpu
))
114 if (!layout
.cpu_name
[0])
115 strncpy(layout
.cpu_name
, cpu
->name
, sizeof(layout
.cpu_name
));
118 if (cpuid_get_max_func() >= 0x16)
119 layout
.cpu_max_non_turbo_frequency
= cpuid_eax(0x16);
122 strcpy(layout
.pch_name
, "Cannonlake-H C246");
125 struct memory_info
*meminfo
= cbmem_find(CBMEM_ID_MEMINFO
);
127 const size_t meminfo_max
= MIN(meminfo
->dimm_cnt
, ARRAY_SIZE(meminfo
->dimm
));
128 for (size_t i
= 0; i
< MIN(meminfo_max
, ARRAY_SIZE(layout
.dimm
)); i
++)
129 copy_meminfo(&meminfo
->dimm
[i
], &layout
.dimm
[i
]);
133 layout
.signature
= CRC(layout
.raw_layout
, sizeof(layout
.raw_layout
), crc32_byte
);
135 printk(BIOS_DEBUG
, "BOARD LAYOUT:\n");
136 printk(BIOS_DEBUG
, " Signature : 0x%x\n", layout
.signature
);
137 printk(BIOS_DEBUG
, " CPU name : %s\n", layout
.cpu_name
);
138 printk(BIOS_DEBUG
, " CPU count : %u\n", layout
.cpu_count
);
139 printk(BIOS_DEBUG
, " CPU freq : %u\n", layout
.cpu_max_non_turbo_frequency
);
140 printk(BIOS_DEBUG
, " PCH name : %s\n", layout
.pch_name
);
141 for (size_t i
= 0; i
< ARRAY_SIZE(layout
.dimm
); i
++)
142 printk(BIOS_DEBUG
, " DRAM SIZE : %u\n", layout
.dimm
[i
].capacity_mib
);
144 if (write_board_settings(&layout
))
145 printk(BIOS_ERR
, "MB: Failed to update Board Layout\n");
148 static void mainboard_init(void *chip_info
)
150 /* Enable internal speaker amplifier */
151 if (get_board_settings()->front_panel_audio
== 2)
152 mb_hda_amp_enable(1);
154 mb_hda_amp_enable(0);
157 static void mainboard_final(struct device
*dev
)
159 update_board_layout();
161 /* Encoding: 0 -> S0, 1 -> S5 */
162 const bool on
= !get_board_settings()->power_state_after_g3
;
164 pmc_soc_set_afterg3_en(on
);
167 static const char *format_pn(const char *prefix
, size_t offset
)
169 static char buffer
[32 + HERMES_SN_PN_LENGTH
] = { 0 };
171 const char *part_num
= eeprom_read_serial(offset
, "N/A");
173 snprintf(buffer
, sizeof(buffer
), "%s%s", prefix
, part_num
);
178 static void mainboard_smbios_strings(struct device
*dev
, struct smbios_type11
*t
)
180 const size_t board_offset
= offsetof(struct eeprom_layout
, board_part_number
);
181 const size_t product_offset
= offsetof(struct eeprom_layout
, product_part_number
);
182 t
->count
= smbios_add_string(t
->eos
, format_pn("Board P/N: ", board_offset
));
183 t
->count
= smbios_add_string(t
->eos
, format_pn("Product P/N: ", product_offset
));
186 #if CONFIG(HAVE_ACPI_TABLES)
187 static void mainboard_acpi_fill_ssdt(const struct device
*dev
)
189 const struct eeprom_board_settings
*const board_cfg
= get_board_settings();
191 const unsigned int usb_power_gpios
[] = { GPP_G0
, GPP_G1
, GPP_G2
, GPP_G3
, GPP_G4
};
193 /* Function pointer to write STXS or CTXS according to EEPROM board setting */
194 int (*acpigen_write_soc_gpio_op
)(unsigned int gpio_num
);
196 if (board_cfg
->usb_powered_in_s5
)
197 acpigen_write_soc_gpio_op
= acpigen_soc_set_tx_gpio
;
199 acpigen_write_soc_gpio_op
= acpigen_soc_clear_tx_gpio
;
201 acpigen_write_method("\\_SB.MPTS", 1);
203 acpigen_write_if_lequal_op_int(ARG0_OP
, 5);
205 for (size_t i
= 0; i
< ARRAY_SIZE(usb_power_gpios
); i
++)
206 acpigen_write_soc_gpio_op(usb_power_gpios
[i
]);
210 if (!board_cfg
->wake_on_usb
) {
212 acpigen_emit_byte(LNOT_OP
);
213 acpigen_emit_byte(LLESS_OP
);
214 acpigen_emit_byte(ARG0_OP
);
215 acpigen_write_integer(ACPI_S3
);
217 acpigen_write_store_int_to_namestr(0, "\\_SB.PCI0.XHCI.PMEE");
226 static void mainboard_enable(struct device
*dev
)
228 /* FIXME: Do runtime configuration once the board is production ready */
229 mb_configure_dp1_pwr(1);
230 mb_configure_dp2_pwr(1);
231 mb_configure_dp3_pwr(1);
233 mb_usb31_rp1_pwr_enable(1);
234 mb_usb31_rp2_pwr_enable(1);
235 mb_usb31_fp_pwr_enable(1);
236 mb_usb2_fp1_pwr_enable(1);
237 mb_usb2_fp2_pwr_enable(1);
239 dev
->ops
->final
= mainboard_final
;
240 dev
->ops
->get_smbios_strings
= mainboard_smbios_strings
;
242 #if CONFIG(HAVE_ACPI_TABLES)
243 dev
->ops
->acpi_fill_ssdt
= mainboard_acpi_fill_ssdt
;
247 struct chip_operations mainboard_ops
= {
248 .init
= mainboard_init
,
249 .enable_dev
= mainboard_enable
,
252 static void log_reset_causes(void)
254 struct chipset_power_state
*ps
= pmc_get_power_state();
257 printk(BIOS_ERR
, "chipset_power_state not found!\n");
262 struct eeprom_reset_cause_regs regs
;
263 uint8_t raw
[sizeof(struct eeprom_reset_cause_regs
)];
266 .gblrst_cause0
= ps
->gblrst_cause
[0],
267 .gblrst_cause1
= ps
->gblrst_cause
[1],
268 .hpr_cause0
= ps
->hpr_cause0
,
272 const size_t base
= offsetof(struct eeprom_layout
, reset_cause_regs
);
273 for (size_t i
= 0; i
< ARRAY_SIZE(reset_cause
.raw
); i
++)
274 eeprom_write_byte(reset_cause
.raw
[i
], base
+ i
);
277 /* Must happen before MPinit */
278 static void mainboard_early(void *unused
)
280 const struct eeprom_board_settings
*const board_cfg
= get_board_settings();
281 config_t
*config
= config_of_soc();
284 config
->deep_s5_enable_ac
= board_cfg
->deep_sx_enabled
;
285 config
->deep_s5_enable_dc
= board_cfg
->deep_sx_enabled
;
287 config
->disable_vmx
= board_cfg
->vtx_disabled
;
289 if (check_signature(offsetof(struct eeprom_layout
, supd
), FSPS_UPD_SIGNATURE
)) {
296 READ_EEPROM_FSP_S((&supd
), FspsConfig
.TurboMode
);
297 config
->cpu_turbo_disable
= !supd
.FspsConfig
.TurboMode
;
303 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE
, BS_ON_EXIT
, mainboard_early
, NULL
);
306 * coreboot only exposes the last framebuffer that is set up.
307 * The ASPEED BMC will always be initialized after the IGD due to its higher
308 * bus number. To have coreboot only expose the IGD framebuffer skip the init
309 * function on the ASPEED.
311 static void mainboard_configure_internal_gfx(void *unused
)
315 if (get_board_settings()->primary_video
== PRIMARY_VIDEO_INTEL
) {
316 dev
= dev_find_device(PCI_VID_ASPEED
, PCI_DID_ASPEED_AST2050_VGA
, NULL
);
317 dev
->on_mainboard
= false;
318 dev
->enabled
= false;
319 dev
->ops
->init
= NULL
;
323 BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES
, BS_ON_ENTRY
, mainboard_configure_internal_gfx
, NULL
)