diff options
Diffstat (limited to 'src/southbridge/intel/lynxpoint')
-rw-r--r-- | src/southbridge/intel/lynxpoint/Kconfig | 9 | ||||
-rw-r--r-- | src/southbridge/intel/lynxpoint/finalize.c | 4 | ||||
-rw-r--r-- | src/southbridge/intel/lynxpoint/me_9.x.c | 81 |
3 files changed, 63 insertions, 31 deletions
diff --git a/src/southbridge/intel/lynxpoint/Kconfig b/src/southbridge/intel/lynxpoint/Kconfig index 3cf9ffe1e5..28ebdb6c2f 100644 --- a/src/southbridge/intel/lynxpoint/Kconfig +++ b/src/southbridge/intel/lynxpoint/Kconfig @@ -67,4 +67,13 @@ config IFD_BIN_PATH string "Path to intel firmware descriptor" default "3rdparty/mainboard/$(MAINBOARDDIR)/descriptor.bin" +config ME_MBP_CLEAR_LATE + bool "Defer wait for ME MBP Cleared" + default y + help + If you set this option to y, the Management Engine driver + will defer waiting for the MBP Cleared indicator until the + finalize step. This can speed up boot time if the ME takes + a long time to indicate this status. + endif diff --git a/src/southbridge/intel/lynxpoint/finalize.c b/src/southbridge/intel/lynxpoint/finalize.c index d81f90ecdb..e3f9cf0fd9 100644 --- a/src/southbridge/intel/lynxpoint/finalize.c +++ b/src/southbridge/intel/lynxpoint/finalize.c @@ -21,10 +21,14 @@ #include <arch/io.h> #include <console/post_codes.h> #include <spi-generic.h> +#include "me.h" #include "pch.h" void intel_pch_finalize_smm(void) { + /* Lock down Management Engine */ + intel_me_finalize_smm(); + /* Set SPI opcode menu */ RCBA16(0x3894) = SPI_OPPREFIX; RCBA16(0x3896) = SPI_OPTYPE; diff --git a/src/southbridge/intel/lynxpoint/me_9.x.c b/src/southbridge/intel/lynxpoint/me_9.x.c index 01eb8447c6..5aa74f015d 100644 --- a/src/southbridge/intel/lynxpoint/me_9.x.c +++ b/src/southbridge/intel/lynxpoint/me_9.x.c @@ -62,6 +62,7 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev); /* MMIO base address for MEI interface */ static u32 mei_base_address; +void intel_me_mbp_clear(device_t dev); #if CONFIG_DEBUG_INTEL_ME static void mei_dump(void *ptr, int dword, int offset, const char *type) @@ -116,14 +117,12 @@ static inline void mei_write_dword_ptr(void *ptr, int offset) mei_dump(ptr, dword, offset, "WRITE"); } -#ifndef __SMM__ static inline void pci_read_dword_ptr(device_t dev, void *ptr, int offset) { u32 dword = pci_read_config32(dev, offset); memcpy(ptr, &dword, sizeof(dword)); mei_dump(ptr, dword, offset, "PCI READ"); } -#endif static inline void read_host_csr(struct mei_csr *csr) { @@ -351,6 +350,47 @@ static inline int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi, return 0; } +/* + * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read + * state machine on the BIOS end doesn't match the ME's state machine. + */ +static void intel_me_mbp_give_up(device_t dev) +{ + struct mei_csr csr; + + pci_write_config32(dev, PCI_ME_H_GS2, PCI_ME_MBP_GIVE_UP); + + read_host_csr(&csr); + csr.reset = 1; + csr.interrupt_generate = 1; + write_host_csr(&csr); +} + +/* + * mbp clear routine. This will wait for the ME to indicate that + * the MBP has been read and cleared. + */ +void intel_me_mbp_clear(device_t dev) +{ + int count; + struct me_hfs2 hfs2; + + /* Wait for the mbp_cleared indicator */ + for (count = ME_RETRY; count > 0; --count) { + pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); + if (hfs2.mbp_cleared) + break; + udelay(ME_DELAY); + } + + if (count == 0) { + printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n"); + intel_me_mbp_give_up(dev); + } else { + printk(BIOS_INFO, "ME: MBP cleared\n"); + } +} + #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) && !defined(__SMM__) static inline void print_cap(const char *name, int state) { @@ -497,6 +537,11 @@ void intel_me_finalize_smm(void) if (!mei_base_address || mei_base_address == 0xfffffff0) return; +#if CONFIG_ME_MBP_CLEAR_LATE + /* Wait for ME MBP Cleared indicator */ + intel_me_mbp_clear(PCH_ME_DEV); +#endif + /* Make sure ME is in a mode that expects EOP */ reg32 = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS); memcpy(&hfs, ®32, sizeof(u32)); @@ -798,23 +843,6 @@ static u32 host_to_me_words_room(void) } #endif -/* - * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read - * state machine on the BIOS end doesn't match the ME's state machine. - */ -static void intel_me_mbp_give_up(device_t dev) -{ - u32 reg32; - struct mei_csr csr; - - reg32 = PCI_ME_MBP_GIVE_UP; - pci_write_config32(dev, PCI_ME_H_GS2, reg32); - read_host_csr(&csr); - csr.reset = 1; - csr.interrupt_generate = 1; - write_host_csr(&csr); -} - struct mbp_payload { mbp_header header; u32 data[0]; @@ -830,7 +858,6 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) u32 me2host_pending; struct mei_csr host; struct me_hfs2 hfs2; - int count; struct mbp_payload *mbp; int i; @@ -876,18 +903,10 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) host.interrupt_generate = 1; write_host_csr(&host); +#if !CONFIG_ME_MBP_CLEAR_LATE /* Wait for the mbp_cleared indicator. */ - for (count = ME_RETRY; count > 0; --count) { - pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); - if (hfs2.mbp_cleared) - break; - udelay(ME_DELAY); - } - - if (count == 0) { - printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n"); - intel_me_mbp_give_up(dev); - } + intel_me_mbp_clear(dev); +#endif /* Dump out the MBP contents. */ #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) |