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>
This commit is contained in:
parent
c063b5d08e
commit
4e722d0766
|
@ -35,8 +35,6 @@
|
||||||
#define NORTHBRIDGE PCI_DEV(0, 0, 0)
|
#define NORTHBRIDGE PCI_DEV(0, 0, 0)
|
||||||
#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
|
#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
|
||||||
#define GMA PCI_DEV (0, 0x2, 0x0)
|
#define GMA PCI_DEV (0, 0x2, 0x0)
|
||||||
#define HECIDEV PCI_DEV(0, 0x16, 0)
|
|
||||||
#define HECIBAR 0x10
|
|
||||||
|
|
||||||
#define FOR_ALL_RANKS \
|
#define FOR_ALL_RANKS \
|
||||||
for (channel = 0; channel < NUM_CHANNELS; channel++) \
|
for (channel = 0; channel < NUM_CHANNELS; channel++) \
|
||||||
|
@ -1505,223 +1503,8 @@ static const struct ram_training *get_cached_training(void)
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: add timeout. */
|
/* TODO: Remove */
|
||||||
static void wait_heci_ready(void)
|
#include "raminit_heci.c"
|
||||||
{
|
|
||||||
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)],
|
|
||||||
¤t_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int have_match_ranks(struct raminfo *info, int channel, int ranks)
|
static int have_match_ranks(struct raminfo *info, int channel, int ranks)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)],
|
||||||
|
¤t_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);
|
||||||
|
}
|
Loading…
Reference in New Issue