aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/skylake/Kconfig1
-rw-r--r--src/soc/intel/skylake/bootblock/pch.c25
-rw-r--r--src/soc/intel/skylake/include/soc/me.h60
-rw-r--r--src/soc/intel/skylake/me.c328
4 files changed, 19 insertions, 395 deletions
diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig
index f66065a28d..e5cc4f7ad2 100644
--- a/src/soc/intel/skylake/Kconfig
+++ b/src/soc/intel/skylake/Kconfig
@@ -54,6 +54,7 @@ config CPU_SPECIFIC_OPTIONS
select SOC_INTEL_COMMON_BLOCK
select SOC_INTEL_COMMON_BLOCK_CPU
select SOC_INTEL_COMMON_BLOCK_CPU_MPINIT
+ select SOC_INTEL_COMMON_BLOCK_CSE
select SOC_INTEL_COMMON_BLOCK_EBDA
select SOC_INTEL_COMMON_BLOCK_FAST_SPI
select SOC_INTEL_COMMON_BLOCK_GPIO
diff --git a/src/soc/intel/skylake/bootblock/pch.c b/src/soc/intel/skylake/bootblock/pch.c
index fdc88f5641..34cfaa34e8 100644
--- a/src/soc/intel/skylake/bootblock/pch.c
+++ b/src/soc/intel/skylake/bootblock/pch.c
@@ -18,6 +18,7 @@
#include <chip.h>
#include <device/device.h>
#include <device/pci_def.h>
+#include <intelblocks/cse.h>
#include <intelblocks/fast_spi.h>
#include <intelblocks/itss.h>
#include <intelblocks/lpc_lib.h>
@@ -157,27 +158,6 @@ static void soc_config_tco(void)
outw(tcocnt, tcobase + TCO1_CNT);
}
-static void enable_heci(void)
-{
- device_t dev = PCH_DEV_CSE;
- u8 pcireg;
-
- /* Assign Resources to HECI1 */
- /* Clear BIT 1-2 of Command Register */
- pcireg = pci_read_config8(dev, PCI_COMMAND);
- pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
- pci_write_config8(dev, PCI_COMMAND, pcireg);
-
- /* Program Temporary BAR for HECI1 */
- pci_write_config32(dev, PCI_BASE_ADDRESS_0, HECI1_BASE_ADDRESS);
- pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0);
-
- /* Enable Bus Master and MMIO Space */
- pcireg = pci_read_config8(dev, PCI_COMMAND);
- pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
- pci_write_config8(dev, PCI_COMMAND, pcireg);
-}
-
void pch_early_iorange_init(void)
{
/* IO Decode Range */
@@ -216,5 +196,6 @@ void pch_early_init(void)
enable_rtc_upper_bank();
- enable_heci();
+ /* initialize Heci interface */
+ heci_init(HECI1_BASE_ADDRESS);
}
diff --git a/src/soc/intel/skylake/include/soc/me.h b/src/soc/intel/skylake/include/soc/me.h
index b94e0ef620..e4b6abf193 100644
--- a/src/soc/intel/skylake/include/soc/me.h
+++ b/src/soc/intel/skylake/include/soc/me.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
- * Copyright (C) 2016 Intel Corporation.
+ * Copyright (C) 2016-2017 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -202,47 +202,6 @@ union me_hfs6 {
} __packed fields;
};
-/*
- * Management Engine MMIO registers
- */
-#define MMIO_ME_CB_WW 0x00
-#define MMIO_HOST_CSR 0x04
-
-union host_csr {
- u32 data;
- struct {
- u32 int_en: 1;
- u32 int_sts: 1;
- u32 int_gen: 1;
- u32 host_ready: 1;
- u32 host_reset: 1;
- u32 rsv: 3;
- u32 host_read_offset: 8;
- u32 host_write_offset: 8;
- u32 me_cir_depth: 8;
- } __packed fields;
-};
-
-#define MMIO_ME_CB_RW 0x08
-#define MMIO_ME_CSR 0x0C
-
-union me_csr {
- u32 data;
- struct {
- u32 int_en: 1;
- u32 int_sts: 1;
- u32 int_gen: 1;
- u32 host_ready: 1;
- u32 host_reset: 1;
- u32 rsv: 3;
- u32 me_read_offset: 8;
- u32 me_write_offset: 8;
- u32 me_cir_buff: 8;
- } __packed fields;
-};
-
-#define MMIO_ME_D0I3 0x800
-
/* Reset Request */
#define MKHI_GLOBAL_RESET 0x0b
@@ -255,23 +214,6 @@ union me_csr {
#define BIOS_HOST_ADD 0x00
#define HECI_MKHI_ADD 0x07
-#define MAX_HECI_MESSAGE 5
-#define HECI_TIMEOUT 15000000 /* 15sec */
-#define HECI_SEND_TIMEOUT 5000000 /* 5sec */
-#define HECI_READ_TIMEOUT 5000000 /* 5sec */
-#define HECI_DELAY 1000 /* 1ms */
-
-union mei_header {
- u32 data;
- struct {
- u32 client_address: 8;
- u32 host_address: 8;
- u32 length: 9;
- u32 reserved: 6;
- u32 is_complete: 1;
- } __packed fields;
-};
-
void intel_me_status(void);
int send_global_reset(void);
diff --git a/src/soc/intel/skylake/me.c b/src/soc/intel/skylake/me.c
index f4df831445..2569bcff00 100644
--- a/src/soc/intel/skylake/me.c
+++ b/src/soc/intel/skylake/me.c
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2016 Intel Corporation.
+ * Copyright (C) 2016-2017 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,40 +15,23 @@
#include <arch/io.h>
#include <commonlib/helpers.h>
+#include <compiler.h>
#include <console/console.h>
#include <device/pci.h>
-#include <device/pci_def.h>
#include <device/pci_ids.h>
+#include <intelblocks/cse.h>
+#include <soc/iomap.h>
+#include <soc/me.h>
+#include <soc/pci_devs.h>
#include <stdint.h>
-#include <compiler.h>
#include <stdlib.h>
#include <string.h>
-#include <soc/iomap.h>
-#include <soc/pci_devs.h>
-#include <soc/me.h>
-#include <delay.h>
-#include <timer.h>
static inline u32 me_read_config32(int offset)
{
return pci_read_config32(PCH_DEV_CSE, offset);
}
-static inline void me_write_config32(int offset, u32 value)
-{
- pci_write_config32(PCH_DEV_CSE, offset, value);
-}
-
-static inline u32 me_read_mmio32(int offset)
-{
- return read32((void *)(HECI1_BASE_ADDRESS + offset));
-}
-
-static inline void me_write_mmio32(u16 offset, u32 value)
-{
- write32((void *)(HECI1_BASE_ADDRESS + offset), value);
-}
-
/* HFSTS1[3:0] Current Working State Values */
static const char * const me_cws_values[] = {
[ME_HFS_CWS_RESET] = "Reset",
@@ -368,291 +351,6 @@ void intel_me_status(void)
}
}
-/*
-* Aligning a byte length to length in dwords.
-*/
-static u32 get_dword_length(u32 byte_length)
-{
- return ALIGN_UP(byte_length, sizeof(uint32_t)) / sizeof(uint32_t);
-}
-
-/*
-* Get remaining message count in dword from circular buffer based on
-* write and read offset.
-*/
-static u32 get_cb_msg_count(u32 data)
-{
- u8 read_offset = data >> 8;
- u8 write_offset = data >> 16;
-
- return get_dword_length(write_offset - read_offset);
-}
-
-static int wait_heci_ready(void)
-{
- struct stopwatch sw;
- int timeout = 0;
- union me_csr csr;
-
- stopwatch_init_msecs_expire(&sw, HECI_TIMEOUT);
- while (1) {
- do {
- csr.data = me_read_mmio32(MMIO_ME_CSR);
- if (csr.fields.host_ready)
- return 0;
- } while (!(timeout = stopwatch_expired(&sw)));
-
- printk(BIOS_ERR, "ME_RDY bit is not set after 15 sec");
- return -1;
- }
-}
-
-static int wait_heci_cb_avail(u32 len)
-{
- struct stopwatch sw;
- union host_csr csr;
-
- csr.data = me_read_mmio32(MMIO_HOST_CSR);
- /*
- * if timeout has happened, return failure as
- * the circular buffer is not empty
- */
- stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT);
- /* Must have room for message and message header */
- while (len > (get_dword_length(csr.fields.me_cir_depth) -
- get_cb_msg_count(csr.data))) {
- if (stopwatch_expired(&sw)) {
- printk(BIOS_ERR,
- "Circular Buffer never emptied within 5 sec");
- return -1;
- }
- /* wait before trying again */
- udelay(HECI_DELAY);
- /* read HOST_CSR for next iteration */
- csr.data = me_read_mmio32(MMIO_HOST_CSR);
- }
- return 0;
-}
-
-static int send_heci_packet(union mei_header *head, u32 len, u32 *payload)
-{
- int sts;
- int index;
- union me_csr csr;
- union host_csr hcsr;
-
- /*
- * wait until there is sufficient room in CB
- */
- sts = wait_heci_cb_avail(len + 1);
- if (sts != 0)
- return -1;
-
- /* Write message header */
- me_write_mmio32(MMIO_ME_CB_WW, head->data);
-
- /* Write message body */
- for (index = 0; index < len; index++)
- me_write_mmio32(MMIO_ME_CB_WW, payload[index]);
-
- /* Set Interrupt Generate bit */
- hcsr.data = me_read_mmio32(MMIO_HOST_CSR);
- hcsr.fields.int_gen = 1;
- me_write_mmio32(MMIO_HOST_CSR, hcsr.data);
-
- /* Check if ME Ready bit is set, if set to 0 then return fatal error */
- csr.data = me_read_mmio32(MMIO_ME_CSR);
- if (csr.fields.host_ready)
- return 0;
- else
- return -1;
-}
-
-static int recv_heci_packet(union mei_header *head, u32 *packet,
- u32 *packet_size)
-{
- union me_csr csr;
- union host_csr hcsr;
- int rec_msg = 0;
- struct stopwatch sw;
- u32 length, index;
-
- /* Clear Interrupt Status bit */
- hcsr.data = me_read_mmio32(MMIO_HOST_CSR);
- hcsr.fields.int_sts = 1;
- me_write_mmio32(MMIO_HOST_CSR, hcsr.data);
-
- /* Check if circular buffer overflow
- * if yes then return fatal error
- */
- csr.data = me_read_mmio32(MMIO_ME_CSR);
- if (get_cb_msg_count(csr.data) >
- get_dword_length(csr.fields.me_cir_buff))
- return -1;
- /*
- * if timeout has happened, return failure as
- * the circular buffer is not empty
- */
- stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT);
- /* go until we got message pkt */
- do {
- if (stopwatch_expired(&sw)) {
- printk(BIOS_ERR,
- "Circular Buffer not filled within 5 sec");
- *packet_size = 0;
- return -1;
- }
- csr.data = me_read_mmio32(MMIO_ME_CSR);
- /* Read one message from HECI buffer */
- if (get_cb_msg_count(csr.data) > 0) {
- head->data = me_read_mmio32(MMIO_ME_CB_RW);
- /* calculate the message length in dword */
- length = get_dword_length(head->fields.length);
- if (head->fields.length == 0) {
- *packet_size = 0;
- goto SET_IG;
- }
- /* Make sure, we have enough space to catch all */
- if (head->fields.length <= *packet_size) {
- csr.data = me_read_mmio32(MMIO_ME_CSR);
- /* get complete message into circular buffer */
- while (length > get_cb_msg_count(csr.data)) {
- udelay(HECI_DELAY);
- csr.data = me_read_mmio32(MMIO_ME_CSR);
- }
- /* here is the message */
- for (index = 0; index < length; index++)
- packet[index] =
- me_read_mmio32(MMIO_ME_CB_RW);
-
- rec_msg = 1;
- *packet_size = head->fields.length;
- } else {
- /* Too small buffer */
- *packet_size = 0;
- return -1;
- }
- }
- } while (!rec_msg);
-
- /*
- * Check if ME Ready bit is set, if set to 0 then return fatal error
- * because ME might have reset during transaction and we might have
- * read a junk data from CB
- */
- csr.data = me_read_mmio32(MMIO_ME_CSR);
- if (!(csr.fields.host_ready))
- return -1;
-SET_IG:
- /* Set Interrupt Generate bit */
- hcsr.data = me_read_mmio32(MMIO_HOST_CSR);
- hcsr.fields.int_gen = 1;
- me_write_mmio32(MMIO_HOST_CSR, hcsr.data);
- return 0;
-}
-
-static int
-send_heci_message(void *msg, int len, u8 hostaddress, u8 clientaddress)
-{
- u8 retry;
- int status = -1;
- u32 cir_buff_depth;
- union host_csr csr;
- union mei_header head;
- int cur = 0;
- u32 slength, rlength;
-
- for (retry = 0; retry < MAX_HECI_MESSAGE; retry++) {
- if (wait_heci_ready() != 0)
- continue;
- /* HECI is ready */
- csr.data = me_read_mmio32(MMIO_HOST_CSR);
- cir_buff_depth = csr.fields.me_cir_depth;
- head.fields.client_address = clientaddress;
- head.fields.host_address = hostaddress;
- while (len > cur) {
- rlength = get_dword_length(len - cur);
- /*
- * Set the message complete bit if this is last packet
- * in message needs to be "less than" to account for
- * the header OR needs to be exact equal to CB depth
- */
- if (rlength <= cir_buff_depth)
- head.fields.is_complete = 1;
- else
- head.fields.is_complete = 0;
- /*
- * calculate length for message header
- * header length = smaller of CB buffer or
- * remaining message
- */
- slength = ((cir_buff_depth <= rlength)
- ? ((cir_buff_depth - 1) * 4)
- : (len - cur));
- head.fields.length = slength;
- head.fields.reserved = 0;
- /*
- * send the current packet
- * (cur should be treated as index for message)
- */
- status = send_heci_packet(&head,
- get_dword_length(head.fields.length), msg);
- if (status != 0)
- break;
- /* update the length information */
- cur += slength;
- msg += cur;
- }
- if (!status)
- break;
- }
- return status;
-}
-
-static int
-recv_heci_message(void *message, u32 *message_size)
-{
- union mei_header head;
- int cur = 0;
- u8 retry;
- int status = -1;
- int msg_complete = 0;
- u32 pkt_buff;
-
- for (retry = 0; retry < MAX_HECI_MESSAGE; retry++) {
- if (wait_heci_ready() != 0)
- continue;
- /* HECI is ready */
- while ((cur < *message_size) && (msg_complete == 0)) {
- pkt_buff = *message_size - cur;
- status = recv_heci_packet(&head, message + (cur >> 2),
- &pkt_buff);
- if (status == -1) {
- *message_size = 0;
- break;
- }
- msg_complete = head.fields.is_complete;
- if (pkt_buff == 0) {
- /* if not in middle of msg and msg complete bit
- * is set then this is a valid zero length msg
- */
- if ((cur == 0) && (msg_complete == 1))
- status = 0;
- else
- status = -1;
- *message_size = 0;
- break;
- }
- cur += pkt_buff;
- }
- if (!status) {
- *message_size = cur;
- break;
- }
- }
- return status;
-}
-
static int send_heci_reset_message(void)
{
int status;
@@ -675,19 +373,21 @@ static int send_heci_reset_message(void)
.req_origin = GR_ORIGIN_BIOS_POST,
.reset_type = GLOBAL_RST_TYPE
};
- u32 reply_size;
+ size_t reply_size;
+
+ heci_reset();
- status = send_heci_message(&msg, sizeof(msg),
- BIOS_HOST_ADD, HECI_MKHI_ADD);
- if (status != 0)
+ status = heci_send(&msg, sizeof(msg), BIOS_HOST_ADD, HECI_MKHI_ADD);
+ if (!status)
return -1;
reply_size = sizeof(reply);
memset(&reply, 0, reply_size);
- if (recv_heci_message(&reply, &reply_size) == -1)
+ status = heci_receive(&reply, &reply_size);
+ if (!status)
return -1;
/* get reply result from HECI MSG */
- if (reply.result != 0) {
+ if (reply.result) {
printk(BIOS_DEBUG, "%s: Exit with Failure\n", __func__);
return -1;
}