void southbridge_smm_clear_state(void) { u32 smi_en; #if CONFIG_ELOG /* Log events from chipset before clearing */ pch_log_state(); #endif printk(BIOS_DEBUG, "Initializing Southbridge SMI..."); printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", get_pmbase()); smi_en = inl(get_pmbase() + SMI_EN); if (smi_en & APMC_EN) { printk(BIOS_INFO, "SMI# handler already enabled?\n"); return; } printk(BIOS_DEBUG, "\n"); /* Dump and clear status registers */ clear_smi_status(); clear_pm1_status(); clear_tco_status(); clear_gpe_status(); }
static void smm_install(void) { device_t dev = PCI_DEV(0, 0, 0); device_t qpdev = PCI_DEV(QUICKPATH_BUS, 0, 1); u32 smm_base = 0xa0000; struct ied_header ied = { .signature = "INTEL RSVD", .size = IED_SIZE, .reserved = {0}, }; /* The first CPU running this gets to copy the SMM handler. But not all * of them. */ if (smm_handler_copied) return; smm_handler_copied = 1; /* enable the SMM memory window */ pci_write_config8(qpdev, QPD0F1_SMRAM, D_OPEN | G_SMRAME | C_BASE_SEG); #if CONFIG_SMM_TSEG smm_base = pci_read_config32(dev, TSEG) & ~1; #endif /* copy the real SMM handler */ printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n", smm_base); memcpy((void *)smm_base, &_binary_smm_start, (size_t)(&_binary_smm_end - &_binary_smm_start)); /* copy the IED header into place */ if (CONFIG_SMM_TSEG_SIZE > IED_SIZE) { /* Top of TSEG region */ smm_base += CONFIG_SMM_TSEG_SIZE - IED_SIZE; printk(BIOS_DEBUG, "Installing IED header to 0x%08x\n", smm_base); memcpy((void *)smm_base, &ied, sizeof(ied)); } wbinvd(); /* close the SMM memory window and enable normal SMM */ pci_write_config8(qpdev, QPD0F1_SMRAM, G_SMRAME | C_BASE_SEG); } void smm_init(void) { #if CONFIG_ELOG /* Log events from chipset before clearing */ pch_log_state(); #endif /* Put SMM code to 0xa0000 */ smm_install(); /* Put relocation code to 0x38000 and relocate SMBASE */ smm_relocate(); /* We're done. Make sure SMIs can happen! */ smi_set_eos(); }
void southbridge_smm_init(void) { u32 smi_en; #if CONFIG_ELOG /* Log events from chipset before clearing */ pch_log_state(); #endif printk(BIOS_DEBUG, "Initializing Southbridge SMI..."); printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", get_pmbase()); smi_en = inl(get_pmbase() + SMI_EN); if (smi_en & APMC_EN) { printk(BIOS_INFO, "SMI# handler already enabled?\n"); return; } printk(BIOS_DEBUG, "\n"); /* Dump and clear status registers */ clear_smi_status(); clear_pm1_status(); clear_tco_status(); clear_gpe_status(); /* Configure events */ enable_pm1(PWRBTN_EN | GBL_EN); disable_gpe(PME_B0_EN); /* Enable SMI generation: * - on TCO events * - on APMC writes (io 0xb2) * - on writes to SLP_EN (sleep states) * - on writes to GBL_RLS (bios commands) * No SMIs: * - on microcontroller writes (io 0x62/0x66) */ enable_smi(TCO_EN | APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS); }
void southbridge_smm_init(void) { u32 smi_en; u16 pm1_en; u32 gpe0_en; #if CONFIG_ELOG /* Log events from chipset before clearing */ pch_log_state(); #endif printk(BIOS_DEBUG, "Initializing southbridge SMI..."); pmbase = pci_read_config32(PCI_DEV(0, 0x1f, 0), PMBASE) & 0xff80; printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", pmbase); smi_en = inl(pmbase + SMI_EN); if (smi_en & APMC_EN) { printk(BIOS_INFO, "SMI# handler already enabled?\n"); return; } printk(BIOS_DEBUG, "\n"); dump_smi_status(reset_smi_status()); dump_pm1_status(reset_pm1_status()); dump_gpe0_status(reset_gpe0_status()); dump_alt_gp_smi_status(reset_alt_gp_smi_status()); dump_tco_status(reset_tco_status()); /* Disable GPE0 PME_B0 */ gpe0_en = inl(pmbase + GPE0_EN); gpe0_en &= ~PME_B0_EN; outl(gpe0_en, pmbase + GPE0_EN); pm1_en = 0; pm1_en |= PWRBTN_EN; pm1_en |= GBL_EN; outw(pm1_en, pmbase + PM1_EN); /* Enable SMI generation: * - on TCO events * - on APMC writes (io 0xb2) * - on writes to SLP_EN (sleep states) * - on writes to GBL_RLS (bios commands) * No SMIs: * - on microcontroller writes (io 0x62/0x66) */ smi_en = 0; /* reset SMI enables */ #if 0 smi_en |= LEGACY_USB2_EN | LEGACY_USB_EN; #endif smi_en |= TCO_EN; smi_en |= APMC_EN; #if DEBUG_PERIODIC_SMIS /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using * periodic SMIs. */ smi_en |= PERIODIC_EN; #endif smi_en |= SLP_SMI_EN; #if 0 smi_en |= BIOS_EN; #endif /* The following need to be on for SMIs to happen */ smi_en |= EOS | GBL_SMI_EN; outl(smi_en, pmbase + SMI_EN); }