1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpigen.h>
7 #include <console/console.h>
9 #include <device/device.h>
10 #include <device/dram/spd.h>
11 #include <device/pci_ids.h>
12 #include <drivers/intel/gma/opregion.h>
14 #include <intelblocks/gpio.h>
15 #include <intelblocks/pmclib.h>
25 const char *mainboard_vbt_filename(void)
27 const struct eeprom_bmc_settings
*bmc_cfg
= get_bmc_settings();
29 if (bmc_cfg
&& bmc_cfg
->efp3_displayport
)
30 return "vbt-avalanche.bin";
32 return "vbt.bin"; /* Poseidon */
35 /* FIXME: Example code below */
37 static void mb_configure_dp1_pwr(bool enable
)
39 gpio_output(GPP_K3
, enable
);
42 static void mb_configure_dp2_pwr(bool enable
)
44 gpio_output(GPP_K4
, enable
);
47 static void mb_configure_dp3_pwr(bool enable
)
49 gpio_output(GPP_K5
, enable
);
52 static void mb_hda_amp_enable(bool enable
)
54 gpio_output(GPP_C19
, enable
);
57 static void mb_usb31_rp1_pwr_enable(bool enable
)
59 gpio_output(GPP_G0
, enable
);
62 static void mb_usb31_rp2_pwr_enable(bool enable
)
64 gpio_output(GPP_G1
, enable
);
67 static void mb_usb31_fp_pwr_enable(bool enable
)
69 gpio_output(GPP_G2
, enable
);
72 static void mb_usb2_fp1_pwr_enable(bool enable
)
74 gpio_output(GPP_G3
, enable
);
77 static void mb_usb2_fp2_pwr_enable(bool enable
)
79 gpio_output(GPP_G4
, enable
);
82 static void copy_meminfo(const struct dimm_info
*dimm
, union eeprom_dimm_layout
*l
)
84 memset(l
, 0, sizeof(*l
));
85 if (dimm
->dimm_size
== 0)
88 strncpy(l
->name
, (char *)dimm
->module_part_number
, sizeof(l
->name
) - 1);
89 l
->capacity_mib
= dimm
->dimm_size
;
90 l
->data_width_bits
= 8 * (1 << (dimm
->bus_width
& 0x7));
91 l
->bus_width_bits
= l
->data_width_bits
+ 8 * ((dimm
->bus_width
>> 3) & 0x3);
92 l
->ranks
= dimm
->rank_per_dimm
;
94 strncpy(l
->manufacturer
, spd_manufacturer_name(dimm
->mod_id
),
95 sizeof(l
->manufacturer
) - 1);
99 * Collect board specific settings and update the CFG EEPROM if necessary.
100 * This allows the BMC webui to display the current hardware configuration.
102 static void update_board_layout(void)
104 struct eeprom_board_layout layout
= {0};
106 printk(BIOS_INFO
, "MB: Collecting Board Layout information\n");
108 /* Update CPU fields */
109 for (struct device
*cpu
= all_devices
; cpu
; cpu
= cpu
->next
) {
110 if (!is_enabled_cpu(cpu
))
113 if (!layout
.cpu_name
[0])
114 strcpy(layout
.cpu_name
, cpu
->name
);
117 if (cpuid_get_max_func() >= 0x16)
118 layout
.cpu_max_non_turbo_frequency
= cpuid_eax(0x16);
121 strcpy(layout
.pch_name
, "Cannonlake-H C246");
124 struct memory_info
*meminfo
= cbmem_find(CBMEM_ID_MEMINFO
);
126 const size_t meminfo_max
= MIN(meminfo
->dimm_cnt
, ARRAY_SIZE(meminfo
->dimm
));
127 for (size_t i
= 0; i
< MIN(meminfo_max
, ARRAY_SIZE(layout
.dimm
)); i
++)
128 copy_meminfo(&meminfo
->dimm
[i
], &layout
.dimm
[i
]);
132 layout
.signature
= CRC(layout
.raw_layout
, sizeof(layout
.raw_layout
), crc32_byte
);
134 printk(BIOS_DEBUG
, "BOARD LAYOUT:\n");
135 printk(BIOS_DEBUG
, " Signature : 0x%x\n", layout
.signature
);
136 printk(BIOS_DEBUG
, " CPU name : %s\n", layout
.cpu_name
);
137 printk(BIOS_DEBUG
, " CPU count : %u\n", layout
.cpu_count
);
138 printk(BIOS_DEBUG
, " CPU freq : %u\n", layout
.cpu_max_non_turbo_frequency
);
139 printk(BIOS_DEBUG
, " PCH name : %s\n", layout
.pch_name
);
140 for (size_t i
= 0; i
< ARRAY_SIZE(layout
.dimm
); i
++)
141 printk(BIOS_DEBUG
, " DRAM SIZE : %u\n", layout
.dimm
[i
].capacity_mib
);
143 if (write_board_settings(&layout
))
144 printk(BIOS_ERR
, "MB: Failed to update Board Layout\n");
147 static void mainboard_init(void *chip_info
)
149 const struct eeprom_board_settings
*const board_cfg
= get_board_settings();
154 /* Enable internal speaker amplifier */
155 if (board_cfg
->front_panel_audio
== 2)
156 mb_hda_amp_enable(1);
158 mb_hda_amp_enable(0);
161 static void mainboard_final(struct device
*dev
)
163 update_board_layout();
165 const struct eeprom_board_settings
*const board_cfg
= get_board_settings();
170 /* Encoding: 0 -> S0, 1 -> S5 */
171 const bool on
= !board_cfg
->power_state_after_g3
;
173 pmc_soc_set_afterg3_en(on
);
176 static const char *format_pn(const char *prefix
, size_t offset
)
178 static char buffer
[32 + HERMES_SN_PN_LENGTH
] = { 0 };
180 const char *part_num
= eeprom_read_serial(offset
, "N/A");
182 snprintf(buffer
, sizeof(buffer
), "%s%s", prefix
, part_num
);
187 static void mainboard_smbios_strings(struct device
*dev
, struct smbios_type11
*t
)
189 const size_t board_offset
= offsetof(struct eeprom_layout
, board_part_number
);
190 const size_t product_offset
= offsetof(struct eeprom_layout
, product_part_number
);
191 t
->count
= smbios_add_string(t
->eos
, format_pn("Board P/N: ", board_offset
));
192 t
->count
= smbios_add_string(t
->eos
, format_pn("Product P/N: ", product_offset
));
195 #if CONFIG(HAVE_ACPI_TABLES)
196 static void mainboard_acpi_fill_ssdt(const struct device
*dev
)
198 const struct eeprom_board_settings
*const board_cfg
= get_board_settings();
203 const unsigned int usb_power_gpios
[] = { GPP_G0
, GPP_G1
, GPP_G2
, GPP_G3
, GPP_G4
};
205 /* Function pointer to write STXS or CTXS according to EEPROM board setting */
206 int (*acpigen_write_soc_gpio_op
)(unsigned int gpio_num
);
208 if (board_cfg
->usb_powered_in_s5
)
209 acpigen_write_soc_gpio_op
= acpigen_soc_set_tx_gpio
;
211 acpigen_write_soc_gpio_op
= acpigen_soc_clear_tx_gpio
;
213 acpigen_write_method("\\_SB.MPTS", 1);
215 acpigen_write_if_lequal_op_int(ARG0_OP
, 5);
217 for (size_t i
= 0; i
< ARRAY_SIZE(usb_power_gpios
); i
++)
218 acpigen_write_soc_gpio_op(usb_power_gpios
[i
]);
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();
285 config
->deep_s5_enable_ac
= board_cfg
->deep_sx_enabled
;
286 config
->deep_s5_enable_dc
= board_cfg
->deep_sx_enabled
;
288 config
->disable_vmx
= board_cfg
->vtx_disabled
;
291 if (check_signature(offsetof(struct eeprom_layout
, supd
), FSPS_UPD_SIGNATURE
)) {
298 READ_EEPROM_FSP_S((&supd
), FspsConfig
.TurboMode
);
299 config
->cpu_turbo_disable
= !supd
.FspsConfig
.TurboMode
;
305 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE
, BS_ON_EXIT
, mainboard_early
, NULL
);
308 * coreboot only exposes the last framebuffer that is set up.
309 * The ASPEED BMC will always be initialized after the IGD due to its higher
310 * bus number. To have coreboot only expose the IGD framebuffer skip the init
311 * function on the ASPEED.
313 static void mainboard_configure_internal_gfx(void *unused
)
316 const struct eeprom_board_settings
*board_cfg
= get_board_settings();
320 if (board_cfg
->primary_video
== PRIMARY_VIDEO_INTEL
) {
321 dev
= dev_find_device(PCI_VID_ASPEED
, PCI_DID_ASPEED_AST2050_VGA
, NULL
);
322 dev
->on_mainboard
= false;
323 dev
->enabled
= false;
324 dev
->ops
->init
= NULL
;
328 BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES
, BS_ON_ENTRY
, mainboard_configure_internal_gfx
, NULL
)