summaryrefslogtreecommitdiffstats
path: root/src/northbridge/intel/ironlake
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2022-02-14 12:33:19 +0100
committerFelix Held <felix-coreboot@felixheld.de>2022-02-15 23:37:06 +0000
commit4e722d0766d42b76793ca5cff6cfc7be47ecd302 (patch)
tree97766b3793ffc2fc3d5efb7c93b7c6b9cdf00497 /src/northbridge/intel/ironlake
parentc063b5d08e1772ab5dda68597079f233f632b2c3 (diff)
downloadcoreboot-4e722d0766d42b76793ca5cff6cfc7be47ecd302.tar.gz
coreboot-4e722d0766d42b76793ca5cff6cfc7be47ecd302.tar.bz2
coreboot-4e722d0766d42b76793ca5cff6cfc7be47ecd302.zip
nb/intel/ironlake: Split out HECI code out of raminit
Move HECI code out of raminit.c into a separate raminit_heci.c file. To preserve reproducibility, use a temporary .c include. This will be gone in a follow-up. Tested with BUILD_TIMELESS=1, Packard Bell MS2290 remains identical. Change-Id: I240552c9628f613fcfa8d2dd09b8e59c87df6019 Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/61928 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Elyes Haouas <ehaouas@noos.fr>
Diffstat (limited to 'src/northbridge/intel/ironlake')
-rw-r--r--src/northbridge/intel/ironlake/raminit.c221
-rw-r--r--src/northbridge/intel/ironlake/raminit_heci.c230
2 files changed, 232 insertions, 219 deletions
diff --git a/src/northbridge/intel/ironlake/raminit.c b/src/northbridge/intel/ironlake/raminit.c
index 9277477a8efd..945e139a7b95 100644
--- a/src/northbridge/intel/ironlake/raminit.c
+++ b/src/northbridge/intel/ironlake/raminit.c
@@ -35,8 +35,6 @@
#define NORTHBRIDGE PCI_DEV(0, 0, 0)
#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
#define GMA PCI_DEV (0, 0x2, 0x0)
-#define HECIDEV PCI_DEV(0, 0x16, 0)
-#define HECIBAR 0x10
#define FOR_ALL_RANKS \
for (channel = 0; channel < NUM_CHANNELS; channel++) \
@@ -1505,223 +1503,8 @@ static const struct ram_training *get_cached_training(void)
NULL);
}
-/* FIXME: add timeout. */
-static void wait_heci_ready(void)
-{
- while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) // = 0x8000000c
- ;
-
- write32((DEFAULT_HECIBAR + 0x4), (read32(DEFAULT_HECIBAR + 0x4) & ~0x10) | 0xc);
-}
-
-/* FIXME: add timeout. */
-static void wait_heci_cb_avail(int len)
-{
- union {
- struct mei_csr csr;
- u32 raw;
- } csr;
-
- while (!(read32(DEFAULT_HECIBAR + 0xc) & 8))
- ;
-
- do {
- csr.raw = read32(DEFAULT_HECIBAR + 0x4);
- } while (len > csr.csr.buffer_depth - (csr.csr.buffer_write_ptr -
- csr.csr.buffer_read_ptr));
-}
-
-static void send_heci_packet(struct mei_header *head, u32 *payload)
-{
- int len = (head->length + 3) / 4;
- int i;
-
- wait_heci_cb_avail(len + 1);
-
- /* FIXME: handle leftovers correctly. */
- write32(DEFAULT_HECIBAR + 0, *(u32 *) head);
- for (i = 0; i < len - 1; i++)
- write32(DEFAULT_HECIBAR + 0, payload[i]);
-
- write32(DEFAULT_HECIBAR + 0, payload[i] & ((1 << (8 * len)) - 1));
- write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 0x4);
-}
-
-static void send_heci_message(u8 *msg, int len, u8 hostaddress, u8 clientaddress)
-{
- struct mei_header head;
- int maxlen;
-
- wait_heci_ready();
- maxlen = (read32(DEFAULT_HECIBAR + 0x4) >> 24) * 4 - 4;
-
- while (len) {
- int cur = len;
- if (cur > maxlen) {
- cur = maxlen;
- head.is_complete = 0;
- } else
- head.is_complete = 1;
- head.length = cur;
- head.reserved = 0;
- head.client_address = clientaddress;
- head.host_address = hostaddress;
- send_heci_packet(&head, (u32 *) msg);
- len -= cur;
- msg += cur;
- }
-}
-
-/* FIXME: Add timeout. */
-static int recv_heci_packet(struct mei_header *head, u32 *packet, u32 *packet_size)
-{
- union {
- struct mei_csr csr;
- u32 raw;
- } csr;
- int i = 0;
-
- write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
- do {
- csr.raw = read32(DEFAULT_HECIBAR + 0xc);
- } while (csr.csr.buffer_write_ptr == csr.csr.buffer_read_ptr);
-
- *(u32 *) head = read32(DEFAULT_HECIBAR + 0x8);
- if (!head->length) {
- write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
- *packet_size = 0;
- return 0;
- }
- if (head->length + 4 > 4 * csr.csr.buffer_depth || head->length > *packet_size) {
- *packet_size = 0;
- return -1;
- }
-
- do {
- csr.raw = read32(DEFAULT_HECIBAR + 0xc);
- } while (((head->length + 3) >> 2) >
- (csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr));
-
- for (i = 0; i < (head->length + 3) >> 2; i++)
- packet[i++] = read32(DEFAULT_HECIBAR + 0x8);
- *packet_size = head->length;
- if (!csr.csr.ready)
- *packet_size = 0;
- write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 4);
- return 0;
-}
-
-union uma_reply {
- struct {
- u8 group_id;
- u8 command;
- u8 reserved;
- u8 result;
- u8 field2;
- u8 unk3[0x48 - 4 - 1];
- };
- u32 dwords[0x48 / sizeof(u32)];
-} __packed;
-
-/* FIXME: Add timeout. */
-static int recv_heci_message(union uma_reply *message, u32 *message_size)
-{
- struct mei_header head;
- int current_position;
-
- current_position = 0;
- while (1) {
- u32 current_size;
- current_size = *message_size - current_position;
- if (recv_heci_packet
- (&head, &message->dwords[current_position / sizeof(u32)],
- &current_size) == -1)
- break;
- if (!current_size)
- break;
- current_position += current_size;
- if (head.is_complete) {
- *message_size = current_position;
- return 0;
- }
-
- if (current_position >= *message_size)
- break;
- }
- *message_size = 0;
- return -1;
-}
-
-static void send_heci_uma_message(const u64 heci_uma_addr, const unsigned int heci_uma_size)
-{
- union uma_reply reply;
-
- struct uma_message {
- u8 group_id;
- u8 cmd;
- u8 reserved;
- u8 result;
- u32 c2;
- u64 heci_uma_addr;
- u32 heci_uma_size;
- u16 c3;
- } __packed msg = {
- .group_id = 0,
- .cmd = MKHI_SET_UMA,
- .reserved = 0,
- .result = 0,
- .c2 = 0x82,
- .heci_uma_addr = heci_uma_addr,
- .heci_uma_size = heci_uma_size,
- .c3 = 0,
- };
- u32 reply_size;
-
- send_heci_message((u8 *) &msg, sizeof(msg), 0, 7);
-
- reply_size = sizeof(reply);
- if (recv_heci_message(&reply, &reply_size) == -1)
- return;
-
- if (reply.command != (MKHI_SET_UMA | (1 << 7)))
- die("HECI init failed\n");
-}
-
-static void setup_heci_uma(struct raminfo *info)
-{
- if (!info->memory_reserved_for_heci_mb && !(pci_read_config32(HECIDEV, 0x40) & 0x20))
- return;
-
- const u64 heci_uma_addr =
- ((u64)
- ((((u64)pci_read_config16(NORTHBRIDGE, TOM)) << 6) -
- info->memory_reserved_for_heci_mb)) << 20;
-
- pci_read_config32(NORTHBRIDGE, DMIBAR);
- if (info->memory_reserved_for_heci_mb) {
- dmibar_clrbits32(DMIVC0RCTL, 1 << 7);
- RCBA32(0x14) &= ~0x80;
- dmibar_clrbits32(DMIVC1RCTL, 1 << 7);
- RCBA32(0x20) &= ~0x80;
- dmibar_clrbits32(DMIVCPRCTL, 1 << 7);
- RCBA32(0x30) &= ~0x80;
- dmibar_clrbits32(DMIVCMRCTL, 1 << 7);
- RCBA32(0x40) &= ~0x80;
-
- RCBA32(0x40) = 0x87000080; // OK
- dmibar_write32(DMIVCMRCTL, 0x87000080); // OK
-
- while ((RCBA16(0x46) & 2) && dmibar_read16(DMIVCMRSTS) & VCMNP)
- ;
- }
-
- mchbar_write32(0x24, 0x10000 + info->memory_reserved_for_heci_mb);
-
- send_heci_uma_message(heci_uma_addr, info->memory_reserved_for_heci_mb);
-
- pci_write_config32(HECIDEV, 0x10, 0x0);
- pci_write_config8(HECIDEV, 0x4, 0x0);
-}
+/* TODO: Remove */
+#include "raminit_heci.c"
static int have_match_ranks(struct raminfo *info, int channel, int ranks)
{
diff --git a/src/northbridge/intel/ironlake/raminit_heci.c b/src/northbridge/intel/ironlake/raminit_heci.c
new file mode 100644
index 000000000000..6af1371b5118
--- /dev/null
+++ b/src/northbridge/intel/ironlake/raminit_heci.c
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <device/mmio.h>
+#include <device/pci_def.h>
+#include <device/pci_ops.h>
+#include <northbridge/intel/ironlake/raminit.h>
+#include <southbridge/intel/ibexpeak/me.h>
+#include <types.h>
+
+#define NORTHBRIDGE PCI_DEV(0, 0, 0)
+#define HECIDEV PCI_DEV(0, 0x16, 0)
+
+/* FIXME: add timeout. */
+static void wait_heci_ready(void)
+{
+ while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) // = 0x8000000c
+ ;
+
+ write32((DEFAULT_HECIBAR + 0x4), (read32(DEFAULT_HECIBAR + 0x4) & ~0x10) | 0xc);
+}
+
+/* FIXME: add timeout. */
+static void wait_heci_cb_avail(int len)
+{
+ union {
+ struct mei_csr csr;
+ u32 raw;
+ } csr;
+
+ while (!(read32(DEFAULT_HECIBAR + 0xc) & 8))
+ ;
+
+ do {
+ csr.raw = read32(DEFAULT_HECIBAR + 0x4);
+ } while (len > csr.csr.buffer_depth - (csr.csr.buffer_write_ptr -
+ csr.csr.buffer_read_ptr));
+}
+
+static void send_heci_packet(struct mei_header *head, u32 *payload)
+{
+ int len = (head->length + 3) / 4;
+ int i;
+
+ wait_heci_cb_avail(len + 1);
+
+ /* FIXME: handle leftovers correctly. */
+ write32(DEFAULT_HECIBAR + 0, *(u32 *) head);
+ for (i = 0; i < len - 1; i++)
+ write32(DEFAULT_HECIBAR + 0, payload[i]);
+
+ write32(DEFAULT_HECIBAR + 0, payload[i] & ((1 << (8 * len)) - 1));
+ write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 0x4);
+}
+
+static void send_heci_message(u8 *msg, int len, u8 hostaddress, u8 clientaddress)
+{
+ struct mei_header head;
+ int maxlen;
+
+ wait_heci_ready();
+ maxlen = (read32(DEFAULT_HECIBAR + 0x4) >> 24) * 4 - 4;
+
+ while (len) {
+ int cur = len;
+ if (cur > maxlen) {
+ cur = maxlen;
+ head.is_complete = 0;
+ } else
+ head.is_complete = 1;
+ head.length = cur;
+ head.reserved = 0;
+ head.client_address = clientaddress;
+ head.host_address = hostaddress;
+ send_heci_packet(&head, (u32 *) msg);
+ len -= cur;
+ msg += cur;
+ }
+}
+
+/* FIXME: Add timeout. */
+static int recv_heci_packet(struct mei_header *head, u32 *packet, u32 *packet_size)
+{
+ union {
+ struct mei_csr csr;
+ u32 raw;
+ } csr;
+ int i = 0;
+
+ write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
+ do {
+ csr.raw = read32(DEFAULT_HECIBAR + 0xc);
+ } while (csr.csr.buffer_write_ptr == csr.csr.buffer_read_ptr);
+
+ *(u32 *) head = read32(DEFAULT_HECIBAR + 0x8);
+ if (!head->length) {
+ write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
+ *packet_size = 0;
+ return 0;
+ }
+ if (head->length + 4 > 4 * csr.csr.buffer_depth || head->length > *packet_size) {
+ *packet_size = 0;
+ return -1;
+ }
+
+ do {
+ csr.raw = read32(DEFAULT_HECIBAR + 0xc);
+ } while (((head->length + 3) >> 2) >
+ (csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr));
+
+ for (i = 0; i < (head->length + 3) >> 2; i++)
+ packet[i++] = read32(DEFAULT_HECIBAR + 0x8);
+ *packet_size = head->length;
+ if (!csr.csr.ready)
+ *packet_size = 0;
+ write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 4);
+ return 0;
+}
+
+union uma_reply {
+ struct {
+ u8 group_id;
+ u8 command;
+ u8 reserved;
+ u8 result;
+ u8 field2;
+ u8 unk3[0x48 - 4 - 1];
+ };
+ u32 dwords[0x48 / sizeof(u32)];
+} __packed;
+
+/* FIXME: Add timeout. */
+static int recv_heci_message(union uma_reply *message, u32 *message_size)
+{
+ struct mei_header head;
+ int current_position;
+
+ current_position = 0;
+ while (1) {
+ u32 current_size;
+ current_size = *message_size - current_position;
+ if (recv_heci_packet
+ (&head, &message->dwords[current_position / sizeof(u32)],
+ &current_size) == -1)
+ break;
+ if (!current_size)
+ break;
+ current_position += current_size;
+ if (head.is_complete) {
+ *message_size = current_position;
+ return 0;
+ }
+
+ if (current_position >= *message_size)
+ break;
+ }
+ *message_size = 0;
+ return -1;
+}
+
+static void send_heci_uma_message(const u64 heci_uma_addr, const unsigned int heci_uma_size)
+{
+ union uma_reply reply;
+
+ struct uma_message {
+ u8 group_id;
+ u8 cmd;
+ u8 reserved;
+ u8 result;
+ u32 c2;
+ u64 heci_uma_addr;
+ u32 heci_uma_size;
+ u16 c3;
+ } __packed msg = {
+ .group_id = 0,
+ .cmd = MKHI_SET_UMA,
+ .reserved = 0,
+ .result = 0,
+ .c2 = 0x82,
+ .heci_uma_addr = heci_uma_addr,
+ .heci_uma_size = heci_uma_size,
+ .c3 = 0,
+ };
+ u32 reply_size;
+
+ send_heci_message((u8 *) &msg, sizeof(msg), 0, 7);
+
+ reply_size = sizeof(reply);
+ if (recv_heci_message(&reply, &reply_size) == -1)
+ return;
+
+ if (reply.command != (MKHI_SET_UMA | (1 << 7)))
+ die("HECI init failed\n");
+}
+
+static void setup_heci_uma(struct raminfo *info)
+{
+ if (!info->memory_reserved_for_heci_mb && !(pci_read_config32(HECIDEV, 0x40) & 0x20))
+ return;
+
+ const u64 heci_uma_addr =
+ ((u64)
+ ((((u64)pci_read_config16(NORTHBRIDGE, TOM)) << 6) -
+ info->memory_reserved_for_heci_mb)) << 20;
+
+ pci_read_config32(NORTHBRIDGE, DMIBAR);
+ if (info->memory_reserved_for_heci_mb) {
+ dmibar_clrbits32(DMIVC0RCTL, 1 << 7);
+ RCBA32(0x14) &= ~0x80;
+ dmibar_clrbits32(DMIVC1RCTL, 1 << 7);
+ RCBA32(0x20) &= ~0x80;
+ dmibar_clrbits32(DMIVCPRCTL, 1 << 7);
+ RCBA32(0x30) &= ~0x80;
+ dmibar_clrbits32(DMIVCMRCTL, 1 << 7);
+ RCBA32(0x40) &= ~0x80;
+
+ RCBA32(0x40) = 0x87000080; // OK
+ dmibar_write32(DMIVCMRCTL, 0x87000080); // OK
+
+ while ((RCBA16(0x46) & 2) && dmibar_read16(DMIVCMRSTS) & VCMNP)
+ ;
+ }
+
+ mchbar_write32(0x24, 0x10000 + info->memory_reserved_for_heci_mb);
+
+ send_heci_uma_message(heci_uma_addr, info->memory_reserved_for_heci_mb);
+
+ pci_write_config32(HECIDEV, 0x10, 0x0);
+ pci_write_config8(HECIDEV, 0x4, 0x0);
+}