2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; version 2 of
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <device/mmio.h>
18 #include <console/console.h>
19 #include <cpu/x86/smm.h>
20 #include <cpu/intel/smm_reloc.h>
21 #include <device/device.h>
22 #include <device/pci.h>
23 #include <soc/iomap.h>
27 /* Save settings which will be committed in SMI functions. */
28 static uint32_t smm_save_params
[SMM_SAVE_PARAM_COUNT
];
30 void smm_southcluster_save_param(int param
, uint32_t data
)
32 smm_save_params
[param
] = data
;
35 void smm_southbridge_clear_state(void)
39 /* Log events from chipset before clearing */
41 southcluster_log_state();
43 printk(BIOS_DEBUG
, "Initializing Southbridge SMI...");
44 printk(BIOS_SPEW
, " pmbase = 0x%04x\n", get_pmbase());
46 smi_en
= inl(get_pmbase() + SMI_EN
);
47 if (smi_en
& APMC_EN
) {
48 printk(BIOS_INFO
, "SMI# handler already enabled?\n");
52 /* Dump and clear status registers */
61 static void smm_southcluster_route_gpios(void)
63 void *gpio_rout
= (void *)(PMC_BASE_ADDRESS
+ GPIO_ROUT
);
64 const unsigned short alt_gpio_smi
= ACPI_BASE_ADDRESS
+ ALT_GPIO_SMI
;
65 uint32_t alt_gpio_reg
= 0;
66 uint32_t route_reg
= smm_save_params
[SMM_SAVE_PARAM_GPIO_ROUTE
];
69 printk(BIOS_DEBUG
, "GPIO_ROUT = %08x\n", route_reg
);
71 /* Start the routing for the specific gpios. */
72 write32(gpio_rout
, route_reg
);
74 /* Enable SMIs for the gpios that are set to trigger the SMI. */
75 for (i
= 0; i
< 16; i
++) {
76 if ((route_reg
& ROUTE_MASK
) == ROUTE_SMI
)
77 alt_gpio_reg
|= (1 << i
);
80 printk(BIOS_DEBUG
, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg
);
82 outl(alt_gpio_reg
, alt_gpio_smi
);
85 void smm_southbridge_enable_smi(void)
87 uint16_t pm1_events
= PWRBTN_EN
| GBL_EN
;
89 printk(BIOS_DEBUG
, "Enabling SMIs.\n");
90 if (!smm_save_params
[SMM_SAVE_PARAM_PCIE_WAKE_ENABLE
])
91 pm1_events
|= PCIEXPWAK_DIS
;
92 enable_pm1(pm1_events
);
93 disable_gpe(PME_B0_EN
);
95 /* Set up the GPIO route. */
96 smm_southcluster_route_gpios();
99 * Enable SMI generation:
100 * - on APMC writes (io 0xb2)
101 * - on writes to SLP_EN (sleep states)
102 * - on writes to GBL_RLS (bios commands)
105 * - on microcontroller writes (io 0x62/0x66)
107 enable_smi(APMC_EN
| SLP_SMI_EN
| GBL_SMI_EN
| EOS
);
110 void smm_setup_structures(void *gnvs
, void *tcg
, void *smi1
)
113 * Issue SMI to set the gnvs pointer in SMM.
114 * tcg and smi1 are unused.
116 * EAX = APM_CNT_GNVS_UPDATE
121 "outb %%al, %%dx\n\t"
122 : /* ignore result */
123 : "a" (APM_CNT_GNVS_UPDATE
),
124 "b" ((uint32_t)gnvs
),