@@ -16,6 +16,7 @@
#include "pci_regs.h" // PCI_INTERRUPT_LINE
#include "post.h"
#include "dev-i440fx.h"
+#include "post.h"
#define I440FX_PAM0 0x59
@@ -64,3 +65,27 @@ void piix4_pm_init(u16 bdf, void *arg)
pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
}
+
+#define PIIX_DEVACTB 0x58
+#define PIIX_APMC_EN (1 << 25)
+
+static int piix4_apmc_is_enabled(u16 bdf)
+{
+ /* check if SMM init is already done */
+ u32 value = pci_config_readl(bdf, PIIX_DEVACTB);
+ return value & PIIX_APMC_EN;
+}
+
+static void piix4_apmc_enable(u16 bdf)
+{
+ /* enable SMI generation when writing to the APMC register */
+ u32 value = pci_config_readl(bdf, PIIX_DEVACTB);
+ pci_config_writel(bdf, PIIX_DEVACTB, value | PIIX_APMC_EN);
+}
+
+void piix4_apmc_detected(u16 bdf, void *arg)
+{
+ struct apmc_ops *ops = arg;
+ ops->is_enabled = piix4_apmc_is_enabled;
+ ops->enable = piix4_apmc_enable;
+}
@@ -7,5 +7,6 @@ void i440fx_shadow_detected(u16 bdf, void *arg);
void piix_isa_bridge_init(u16 bdf, void *arg);
void piix_ide_init(u16 bdf, void *arg);
void piix4_pm_init(u16 bdf, void *arg);
+void piix4_apmc_detected(u16 bdf, void *arg);
#endif // __I440FX_H
@@ -10,4 +10,10 @@ struct pam_regs
u32 pam0;
};
+struct apmc_ops
+{
+ int (*is_enabled)(u16 bdf);
+ void (*enable)(u16 bdf);
+};
+
#endif /* __POST_H */
@@ -10,6 +10,8 @@
#include "config.h" // CONFIG_*
#include "ioport.h" // outb
#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "post.h"
+#include "dev-i440fx.h"
ASM32FLAT(
".global smm_relocation_start\n"
@@ -72,6 +74,13 @@ ASM32FLAT(
extern u8 smm_relocation_start, smm_relocation_end;
extern u8 smm_code_start, smm_code_end;
+static const struct pci_device_id apmc_ops_tbl[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+ piix4_apmc_detected),
+
+ PCI_DEVICE_END,
+};
+
void
smm_init(void)
{
@@ -84,8 +93,8 @@ smm_init(void)
dprintf(3, "init smm\n");
// This code is hardcoded for PIIX4 Power Management device.
- int bdf = pci_find_device(PCI_VENDOR_ID_INTEL
- , PCI_DEVICE_ID_INTEL_82371AB_3);
+ struct apmc_ops apmc_ops;
+ int bdf = pci_find_init_device(apmc_ops_tbl, &apmc_ops);
if (bdf < 0)
// Device not found
return;
@@ -95,8 +104,7 @@ smm_init(void)
return;
/* check if SMM init is already done */
- u32 value = pci_config_readl(bdf, 0x58);
- if (value & (1 << 25))
+ if (apmc_ops.is_enabled(bdf))
return;
/* enable the SMM memory window */
@@ -110,7 +118,7 @@ smm_init(void)
&smm_relocation_end - &smm_relocation_start);
/* enable SMI generation when writing to the APMC register */
- pci_config_writel(bdf, 0x58, value | (1 << 25));
+ apmc_ops.enable(bdf);
/* init APM status port */
outb(0x01, PORT_SMI_STATUS);
move out piix4 specific logic to dev-i440fx.c by using pci_find_init_device(). Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> --- src/dev-i440fx.c | 25 +++++++++++++++++++++++++ src/dev-i440fx.h | 1 + src/post.h | 6 ++++++ src/smm.c | 18 +++++++++++++----- 4 files changed, 45 insertions(+), 5 deletions(-)