<p>Subrata Banik has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/22395">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">soc/intel/skylake: Make use of common CSE code for skylake<br><br>TEST=Ensures global reset could able to reset system.<br><br>Change-Id: I11ce1812a5a0aa2da6b414555374460d606e220e<br>Signed-off-by: Subrata Banik <subrata.banik@intel.com><br>---<br>M src/soc/intel/skylake/Kconfig<br>M src/soc/intel/skylake/bootblock/pch.c<br>M src/soc/intel/skylake/me.c<br>3 files changed, 20 insertions(+), 319 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/95/22395/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig<br>index f830f54..c4957ae 100644<br>--- a/src/soc/intel/skylake/Kconfig<br>+++ b/src/soc/intel/skylake/Kconfig<br>@@ -54,6 +54,7 @@<br> select SOC_INTEL_COMMON_BLOCK<br> select SOC_INTEL_COMMON_BLOCK_CPU<br> select SOC_INTEL_COMMON_BLOCK_CPU_MPINIT<br>+ select SOC_INTEL_COMMON_BLOCK_CSE<br> select SOC_INTEL_COMMON_BLOCK_EBDA<br> select SOC_INTEL_COMMON_BLOCK_FAST_SPI<br> select SOC_INTEL_COMMON_BLOCK_GPIO<br>diff --git a/src/soc/intel/skylake/bootblock/pch.c b/src/soc/intel/skylake/bootblock/pch.c<br>index fdc88f5..34cfaa3 100644<br>--- a/src/soc/intel/skylake/bootblock/pch.c<br>+++ b/src/soc/intel/skylake/bootblock/pch.c<br>@@ -18,6 +18,7 @@<br> #include <chip.h><br> #include <device/device.h><br> #include <device/pci_def.h><br>+#include <intelblocks/cse.h><br> #include <intelblocks/fast_spi.h><br> #include <intelblocks/itss.h><br> #include <intelblocks/lpc_lib.h><br>@@ -157,27 +158,6 @@<br> outw(tcocnt, tcobase + TCO1_CNT);<br> }<br> <br>-static void enable_heci(void)<br>-{<br>- device_t dev = PCH_DEV_CSE;<br>- u8 pcireg;<br>-<br>- /* Assign Resources to HECI1 */<br>- /* Clear BIT 1-2 of Command Register */<br>- pcireg = pci_read_config8(dev, PCI_COMMAND);<br>- pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);<br>- pci_write_config8(dev, PCI_COMMAND, pcireg);<br>-<br>- /* Program Temporary BAR for HECI1 */<br>- pci_write_config32(dev, PCI_BASE_ADDRESS_0, HECI1_BASE_ADDRESS);<br>- pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0);<br>-<br>- /* Enable Bus Master and MMIO Space */<br>- pcireg = pci_read_config8(dev, PCI_COMMAND);<br>- pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;<br>- pci_write_config8(dev, PCI_COMMAND, pcireg);<br>-}<br>-<br> void pch_early_iorange_init(void)<br> {<br> /* IO Decode Range */<br>@@ -216,5 +196,6 @@<br> <br> enable_rtc_upper_bank();<br> <br>- enable_heci();<br>+ /* initialize Heci interface */<br>+ heci_init(HECI1_BASE_ADDRESS);<br> }<br>diff --git a/src/soc/intel/skylake/me.c b/src/soc/intel/skylake/me.c<br>index f4df831..9a6d9b0 100644<br>--- a/src/soc/intel/skylake/me.c<br>+++ b/src/soc/intel/skylake/me.c<br>@@ -1,7 +1,7 @@<br> /*<br> * This file is part of the coreboot project.<br> *<br>- * Copyright (C) 2016 Intel Corporation.<br>+ * Copyright (C) 2016-2017 Intel Corporation.<br> *<br> * This program is free software; you can redistribute it and/or modify<br> * it under the terms of the GNU General Public License as published by<br>@@ -15,18 +15,19 @@<br> <br> #include <arch/io.h><br> #include <commonlib/helpers.h><br>+#include <compiler.h><br> #include <console/console.h><br>+#include <delay.h><br> #include <device/pci.h><br> #include <device/pci_def.h><br> #include <device/pci_ids.h><br>+#include <intelblocks/cse.h><br>+#include <soc/iomap.h><br>+#include <soc/me.h><br>+#include <soc/pci_devs.h><br> #include <stdint.h><br>-#include <compiler.h><br> #include <stdlib.h><br> #include <string.h><br>-#include <soc/iomap.h><br>-#include <soc/pci_devs.h><br>-#include <soc/me.h><br>-#include <delay.h><br> #include <timer.h><br> <br> static inline u32 me_read_config32(int offset)<br>@@ -368,291 +369,6 @@<br> }<br> }<br> <br>-/*<br>-* Aligning a byte length to length in dwords.<br>-*/<br>-static u32 get_dword_length(u32 byte_length)<br>-{<br>- return ALIGN_UP(byte_length, sizeof(uint32_t)) / sizeof(uint32_t);<br>-}<br>-<br>-/*<br>-* Get remaining message count in dword from circular buffer based on<br>-* write and read offset.<br>-*/<br>-static u32 get_cb_msg_count(u32 data)<br>-{<br>- u8 read_offset = data >> 8;<br>- u8 write_offset = data >> 16;<br>-<br>- return get_dword_length(write_offset - read_offset);<br>-}<br>-<br>-static int wait_heci_ready(void)<br>-{<br>- struct stopwatch sw;<br>- int timeout = 0;<br>- union me_csr csr;<br>-<br>- stopwatch_init_msecs_expire(&sw, HECI_TIMEOUT);<br>- while (1) {<br>- do {<br>- csr.data = me_read_mmio32(MMIO_ME_CSR);<br>- if (csr.fields.host_ready)<br>- return 0;<br>- } while (!(timeout = stopwatch_expired(&sw)));<br>-<br>- printk(BIOS_ERR, "ME_RDY bit is not set after 15 sec");<br>- return -1;<br>- }<br>-}<br>-<br>-static int wait_heci_cb_avail(u32 len)<br>-{<br>- struct stopwatch sw;<br>- union host_csr csr;<br>-<br>- csr.data = me_read_mmio32(MMIO_HOST_CSR);<br>- /*<br>- * if timeout has happened, return failure as<br>- * the circular buffer is not empty<br>- */<br>- stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT);<br>- /* Must have room for message and message header */<br>- while (len > (get_dword_length(csr.fields.me_cir_depth) -<br>- get_cb_msg_count(csr.data))) {<br>- if (stopwatch_expired(&sw)) {<br>- printk(BIOS_ERR,<br>- "Circular Buffer never emptied within 5 sec");<br>- return -1;<br>- }<br>- /* wait before trying again */<br>- udelay(HECI_DELAY);<br>- /* read HOST_CSR for next iteration */<br>- csr.data = me_read_mmio32(MMIO_HOST_CSR);<br>- }<br>- return 0;<br>-}<br>-<br>-static int send_heci_packet(union mei_header *head, u32 len, u32 *payload)<br>-{<br>- int sts;<br>- int index;<br>- union me_csr csr;<br>- union host_csr hcsr;<br>-<br>- /*<br>- * wait until there is sufficient room in CB<br>- */<br>- sts = wait_heci_cb_avail(len + 1);<br>- if (sts != 0)<br>- return -1;<br>-<br>- /* Write message header */<br>- me_write_mmio32(MMIO_ME_CB_WW, head->data);<br>-<br>- /* Write message body */<br>- for (index = 0; index < len; index++)<br>- me_write_mmio32(MMIO_ME_CB_WW, payload[index]);<br>-<br>- /* Set Interrupt Generate bit */<br>- hcsr.data = me_read_mmio32(MMIO_HOST_CSR);<br>- hcsr.fields.int_gen = 1;<br>- me_write_mmio32(MMIO_HOST_CSR, hcsr.data);<br>-<br>- /* Check if ME Ready bit is set, if set to 0 then return fatal error */<br>- csr.data = me_read_mmio32(MMIO_ME_CSR);<br>- if (csr.fields.host_ready)<br>- return 0;<br>- else<br>- return -1;<br>-}<br>-<br>-static int recv_heci_packet(union mei_header *head, u32 *packet,<br>- u32 *packet_size)<br>-{<br>- union me_csr csr;<br>- union host_csr hcsr;<br>- int rec_msg = 0;<br>- struct stopwatch sw;<br>- u32 length, index;<br>-<br>- /* Clear Interrupt Status bit */<br>- hcsr.data = me_read_mmio32(MMIO_HOST_CSR);<br>- hcsr.fields.int_sts = 1;<br>- me_write_mmio32(MMIO_HOST_CSR, hcsr.data);<br>-<br>- /* Check if circular buffer overflow<br>- * if yes then return fatal error<br>- */<br>- csr.data = me_read_mmio32(MMIO_ME_CSR);<br>- if (get_cb_msg_count(csr.data) ><br>- get_dword_length(csr.fields.me_cir_buff))<br>- return -1;<br>- /*<br>- * if timeout has happened, return failure as<br>- * the circular buffer is not empty<br>- */<br>- stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT);<br>- /* go until we got message pkt */<br>- do {<br>- if (stopwatch_expired(&sw)) {<br>- printk(BIOS_ERR,<br>- "Circular Buffer not filled within 5 sec");<br>- *packet_size = 0;<br>- return -1;<br>- }<br>- csr.data = me_read_mmio32(MMIO_ME_CSR);<br>- /* Read one message from HECI buffer */<br>- if (get_cb_msg_count(csr.data) > 0) {<br>- head->data = me_read_mmio32(MMIO_ME_CB_RW);<br>- /* calculate the message length in dword */<br>- length = get_dword_length(head->fields.length);<br>- if (head->fields.length == 0) {<br>- *packet_size = 0;<br>- goto SET_IG;<br>- }<br>- /* Make sure, we have enough space to catch all */<br>- if (head->fields.length <= *packet_size) {<br>- csr.data = me_read_mmio32(MMIO_ME_CSR);<br>- /* get complete message into circular buffer */<br>- while (length > get_cb_msg_count(csr.data)) {<br>- udelay(HECI_DELAY);<br>- csr.data = me_read_mmio32(MMIO_ME_CSR);<br>- }<br>- /* here is the message */<br>- for (index = 0; index < length; index++)<br>- packet[index] =<br>- me_read_mmio32(MMIO_ME_CB_RW);<br>-<br>- rec_msg = 1;<br>- *packet_size = head->fields.length;<br>- } else {<br>- /* Too small buffer */<br>- *packet_size = 0;<br>- return -1;<br>- }<br>- }<br>- } while (!rec_msg);<br>-<br>- /*<br>- * Check if ME Ready bit is set, if set to 0 then return fatal error<br>- * because ME might have reset during transaction and we might have<br>- * read a junk data from CB<br>- */<br>- csr.data = me_read_mmio32(MMIO_ME_CSR);<br>- if (!(csr.fields.host_ready))<br>- return -1;<br>-SET_IG:<br>- /* Set Interrupt Generate bit */<br>- hcsr.data = me_read_mmio32(MMIO_HOST_CSR);<br>- hcsr.fields.int_gen = 1;<br>- me_write_mmio32(MMIO_HOST_CSR, hcsr.data);<br>- return 0;<br>-}<br>-<br>-static int<br>-send_heci_message(void *msg, int len, u8 hostaddress, u8 clientaddress)<br>-{<br>- u8 retry;<br>- int status = -1;<br>- u32 cir_buff_depth;<br>- union host_csr csr;<br>- union mei_header head;<br>- int cur = 0;<br>- u32 slength, rlength;<br>-<br>- for (retry = 0; retry < MAX_HECI_MESSAGE; retry++) {<br>- if (wait_heci_ready() != 0)<br>- continue;<br>- /* HECI is ready */<br>- csr.data = me_read_mmio32(MMIO_HOST_CSR);<br>- cir_buff_depth = csr.fields.me_cir_depth;<br>- head.fields.client_address = clientaddress;<br>- head.fields.host_address = hostaddress;<br>- while (len > cur) {<br>- rlength = get_dword_length(len - cur);<br>- /*<br>- * Set the message complete bit if this is last packet<br>- * in message needs to be "less than" to account for<br>- * the header OR needs to be exact equal to CB depth<br>- */<br>- if (rlength <= cir_buff_depth)<br>- head.fields.is_complete = 1;<br>- else<br>- head.fields.is_complete = 0;<br>- /*<br>- * calculate length for message header<br>- * header length = smaller of CB buffer or<br>- * remaining message<br>- */<br>- slength = ((cir_buff_depth <= rlength)<br>- ? ((cir_buff_depth - 1) * 4)<br>- : (len - cur));<br>- head.fields.length = slength;<br>- head.fields.reserved = 0;<br>- /*<br>- * send the current packet<br>- * (cur should be treated as index for message)<br>- */<br>- status = send_heci_packet(&head,<br>- get_dword_length(head.fields.length), msg);<br>- if (status != 0)<br>- break;<br>- /* update the length information */<br>- cur += slength;<br>- msg += cur;<br>- }<br>- if (!status)<br>- break;<br>- }<br>- return status;<br>-}<br>-<br>-static int<br>-recv_heci_message(void *message, u32 *message_size)<br>-{<br>- union mei_header head;<br>- int cur = 0;<br>- u8 retry;<br>- int status = -1;<br>- int msg_complete = 0;<br>- u32 pkt_buff;<br>-<br>- for (retry = 0; retry < MAX_HECI_MESSAGE; retry++) {<br>- if (wait_heci_ready() != 0)<br>- continue;<br>- /* HECI is ready */<br>- while ((cur < *message_size) && (msg_complete == 0)) {<br>- pkt_buff = *message_size - cur;<br>- status = recv_heci_packet(&head, message + (cur >> 2),<br>- &pkt_buff);<br>- if (status == -1) {<br>- *message_size = 0;<br>- break;<br>- }<br>- msg_complete = head.fields.is_complete;<br>- if (pkt_buff == 0) {<br>- /* if not in middle of msg and msg complete bit<br>- * is set then this is a valid zero length msg<br>- */<br>- if ((cur == 0) && (msg_complete == 1))<br>- status = 0;<br>- else<br>- status = -1;<br>- *message_size = 0;<br>- break;<br>- }<br>- cur += pkt_buff;<br>- }<br>- if (!status) {<br>- *message_size = cur;<br>- break;<br>- }<br>- }<br>- return status;<br>-}<br>-<br> static int send_heci_reset_message(void)<br> {<br> int status;<br>@@ -672,20 +388,23 @@<br> } __packed;<br> struct reset_message msg = {<br> .cmd = MKHI_GLOBAL_RESET,<br>+ .group_id = 0,<br>+ .reserved = 0,<br>+ .result = 0,<br> .req_origin = GR_ORIGIN_BIOS_POST,<br> .reset_type = GLOBAL_RST_TYPE<br> };<br>- u32 reply_size;<br>+ size_t reply_size;<br> <br>- status = send_heci_message(&msg, sizeof(msg),<br>- BIOS_HOST_ADD, HECI_MKHI_ADD);<br>- if (status != 0)<br>+ heci_reset();<br>+<br>+ status = heci_send(&msg, sizeof(msg), BIOS_HOST_ADD, HECI_MKHI_ADD);<br>+ if (status != 1)<br> return -1;<br> <br> reply_size = sizeof(reply);<br> memset(&reply, 0, reply_size);<br>- if (recv_heci_message(&reply, &reply_size) == -1)<br>- return -1;<br>+ heci_receive(&reply, &reply_size);<br> /* get reply result from HECI MSG */<br> if (reply.result != 0) {<br> printk(BIOS_DEBUG, "%s: Exit with Failure\n", __func__);<br></pre><p>To view, visit <a href="https://review.coreboot.org/22395">change 22395</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/22395"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I11ce1812a5a0aa2da6b414555374460d606e220e </div>
<div style="display:none"> Gerrit-Change-Number: 22395 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Subrata Banik <subrata.banik@intel.com> </div>