blob: ed83173e6f45d2ca61a771846c4b2dc9ed391ff2 [file] [log] [blame]
Angel Ponsc3f58f62020-04-05 15:46:41 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin7837be62013-10-21 22:32:00 -05002
Aaron Durbin7837be62013-10-21 22:32:00 -05003#include <arch/io.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Angel Ponsc5bcd282020-07-07 18:16:35 +02005#include <console/console.h>
Aaron Durbin7837be62013-10-21 22:32:00 -05006#include <cpu/x86/smm.h>
Kyösti Mälkkifaf20d32019-08-14 05:41:41 +03007#include <cpu/intel/smm_reloc.h>
Angel Ponsc5bcd282020-07-07 18:16:35 +02008#include <device/device.h>
9#include <device/pci.h>
Julius Werner18ea2d32014-10-07 16:42:17 -070010#include <soc/iomap.h>
Angel Ponsb5320b22020-07-07 18:27:30 +020011#include <soc/pm.h>
Julius Werner18ea2d32014-10-07 16:42:17 -070012#include <soc/smm.h>
Aaron Durbin7837be62013-10-21 22:32:00 -050013
Kein Yuan35110232014-02-22 12:26:55 -080014/* Save settings which will be committed in SMI functions. */
15static uint32_t smm_save_params[SMM_SAVE_PARAM_COUNT];
Aaron Durbin59a4cd52013-11-11 12:09:28 -060016
Kyösti Mälkkifaf20d32019-08-14 05:41:41 +030017void smm_southcluster_save_param(int param, uint32_t data)
Aaron Durbin59a4cd52013-11-11 12:09:28 -060018{
Kein Yuan35110232014-02-22 12:26:55 -080019 smm_save_params[param] = data;
Aaron Durbin59a4cd52013-11-11 12:09:28 -060020}
21
Kyösti Mälkkifaf20d32019-08-14 05:41:41 +030022void smm_southbridge_clear_state(void)
Aaron Durbin7837be62013-10-21 22:32:00 -050023{
24 uint32_t smi_en;
25
26 /* Log events from chipset before clearing */
Kyösti Mälkki056fbe42019-11-06 12:07:05 +020027 if (CONFIG(ELOG))
28 southcluster_log_state();
Aaron Durbin7837be62013-10-21 22:32:00 -050029
Aaron Durbin7837be62013-10-21 22:32:00 -050030
31 smi_en = inl(get_pmbase() + SMI_EN);
32 if (smi_en & APMC_EN) {
33 printk(BIOS_INFO, "SMI# handler already enabled?\n");
34 return;
35 }
36
37 /* Dump and clear status registers */
38 clear_smi_status();
39 clear_pm1_status();
40 clear_tco_status();
41 clear_gpe_status();
Aaron Durbin9f83e872013-11-11 14:45:27 -060042 clear_alt_status();
Aaron Durbin19edc3a2014-01-09 11:17:37 -060043 clear_pmc_status();
Aaron Durbin7837be62013-10-21 22:32:00 -050044}
45
Kyösti Mälkkifaf20d32019-08-14 05:41:41 +030046static void smm_southcluster_route_gpios(void)
Aaron Durbin59a4cd52013-11-11 12:09:28 -060047{
Angel Ponse80d17f2020-07-07 17:25:38 +020048 void *gpio_rout = (void *)(PMC_BASE_ADDRESS + GPIO_ROUT);
Aaron Durbin59a4cd52013-11-11 12:09:28 -060049 const unsigned short alt_gpio_smi = ACPI_BASE_ADDRESS + ALT_GPIO_SMI;
50 uint32_t alt_gpio_reg = 0;
Kein Yuan35110232014-02-22 12:26:55 -080051 uint32_t route_reg = smm_save_params[SMM_SAVE_PARAM_GPIO_ROUTE];
Aaron Durbin59a4cd52013-11-11 12:09:28 -060052 int i;
53
54 printk(BIOS_DEBUG, "GPIO_ROUT = %08x\n", route_reg);
55
56 /* Start the routing for the specific gpios. */
57 write32(gpio_rout, route_reg);
58
59 /* Enable SMIs for the gpios that are set to trigger the SMI. */
60 for (i = 0; i < 16; i++) {
Angel Ponsc5bcd282020-07-07 18:16:35 +020061 if ((route_reg & ROUTE_MASK) == ROUTE_SMI)
Aaron Durbin59a4cd52013-11-11 12:09:28 -060062 alt_gpio_reg |= (1 << i);
Angel Ponsc5bcd282020-07-07 18:16:35 +020063
Aaron Durbin59a4cd52013-11-11 12:09:28 -060064 route_reg >>= 2;
65 }
66 printk(BIOS_DEBUG, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg);
67
68 outl(alt_gpio_reg, alt_gpio_smi);
69}
70
Kyösti Mälkki0778c862020-06-10 12:44:03 +030071static void smm_southbridge_enable(uint16_t pm1_events)
Aaron Durbin7837be62013-10-21 22:32:00 -050072{
Aaron Durbin59a4cd52013-11-11 12:09:28 -060073
Aaron Durbin7837be62013-10-21 22:32:00 -050074 printk(BIOS_DEBUG, "Enabling SMIs.\n");
Kein Yuan35110232014-02-22 12:26:55 -080075 if (!smm_save_params[SMM_SAVE_PARAM_PCIE_WAKE_ENABLE])
76 pm1_events |= PCIEXPWAK_DIS;
Angel Pons26b49cc2020-07-07 17:17:51 +020077
Kein Yuan35110232014-02-22 12:26:55 -080078 enable_pm1(pm1_events);
Aaron Durbin7837be62013-10-21 22:32:00 -050079 disable_gpe(PME_B0_EN);
80
Aaron Durbin59a4cd52013-11-11 12:09:28 -060081 /* Set up the GPIO route. */
Kyösti Mälkkifaf20d32019-08-14 05:41:41 +030082 smm_southcluster_route_gpios();
Aaron Durbin59a4cd52013-11-11 12:09:28 -060083
Angel Pons26b49cc2020-07-07 17:17:51 +020084 /*
85 * Enable SMI generation:
Aaron Durbin7837be62013-10-21 22:32:00 -050086 * - on APMC writes (io 0xb2)
87 * - on writes to SLP_EN (sleep states)
88 * - on writes to GBL_RLS (bios commands)
89 * No SMIs:
Aaron Durbin766482d2014-01-09 10:44:06 -060090 * - on TCO events
Aaron Durbin7837be62013-10-21 22:32:00 -050091 * - on microcontroller writes (io 0x62/0x66)
92 */
Aaron Durbin766482d2014-01-09 10:44:06 -060093 enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS);
Aaron Durbin7837be62013-10-21 22:32:00 -050094}
95
Kyösti Mälkki0778c862020-06-10 12:44:03 +030096void global_smi_enable(void)
97{
98 smm_southbridge_enable(PWRBTN_EN | GBL_EN);
99}