[coreboot-gerrit] New patch to review for coreboot: marvell/mvmap2315: add IPC driver
hakim giydan (hgiydan@marvell.com)
gerrit at coreboot.org
Fri Jul 1 21:41:35 CEST 2016
hakim giydan (hgiydan at marvell.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15529
-gerrit
commit ea6cbf0964c8f369621282a69b05c157038638c5
Author: Hakim Giydan <hgiydan at marvell.com>
Date: Fri Jul 1 12:07:57 2016 -0700
marvell/mvmap2315: add IPC driver
IPC is the interface between the SP and the MCU
Change-Id: I003f6929b00476d46be931773cd35418fe6622a6
Signed-off-by: Hakim Giydan <hgiydan at marvell.com>
---
src/soc/marvell/mvmap2315/Makefile.inc | 1 +
src/soc/marvell/mvmap2315/include/soc/addressmap.h | 4 +
src/soc/marvell/mvmap2315/include/soc/gic.h | 2 +
src/soc/marvell/mvmap2315/include/soc/ipc.h | 115 ++++++++++++++++
src/soc/marvell/mvmap2315/ipc.c | 151 +++++++++++++++++++++
src/soc/marvell/mvmap2315/power.c | 12 +-
src/soc/marvell/mvmap2315/romstage.c | 9 +-
7 files changed, 290 insertions(+), 4 deletions(-)
diff --git a/src/soc/marvell/mvmap2315/Makefile.inc b/src/soc/marvell/mvmap2315/Makefile.inc
index 0e10a94..48ce8c0 100644
--- a/src/soc/marvell/mvmap2315/Makefile.inc
+++ b/src/soc/marvell/mvmap2315/Makefile.inc
@@ -33,6 +33,7 @@ romstage-y += bootrom.c
romstage-y += cbmem.c
romstage-y += clock.c
romstage-y += gic.c
+romstage-y += ipc.c
romstage-y += media.c
romstage-y += monotonic_timer.c
romstage-y += pinconfig.c
diff --git a/src/soc/marvell/mvmap2315/include/soc/addressmap.h b/src/soc/marvell/mvmap2315/include/soc/addressmap.h
index a54403e..2ecfab0 100644
--- a/src/soc/marvell/mvmap2315/include/soc/addressmap.h
+++ b/src/soc/marvell/mvmap2315/include/soc/addressmap.h
@@ -36,6 +36,10 @@ enum {
MVMAP2315_PADWRAP_BASE = 0xE0140000,
MVMAP2315_WDT0_BASE = 0XE1010000,
MVMAP2315_TIMER0_BASE = 0xE1020000,
+ MVMAP2315_IPC_SP_BASE = 0xED0C2000,
+ MVMAP2315_IPC_MCU_BASE = 0xED0C2100,
+ MVMAP2315_IPC_BUFFER_SP_BASE = 0xEE03FF0C,
+ MVMAP2315_IPC_BUFFER_MCU_BASE = 0xEE03FF8C,
MVMAP2315_MPMU_CLK_BASE = 0xEF000800,
MVMAP2315_A2BUS_BANKED_REGS_BASE = 0xF0000000,
MVMAP2315_A2BUS_ALIAS6_REGS_BASE = 0xF0002000,
diff --git a/src/soc/marvell/mvmap2315/include/soc/gic.h b/src/soc/marvell/mvmap2315/include/soc/gic.h
index 520ea51..310680f 100644
--- a/src/soc/marvell/mvmap2315/include/soc/gic.h
+++ b/src/soc/marvell/mvmap2315/include/soc/gic.h
@@ -19,6 +19,8 @@
#include <stdlib.h>
#include <types.h>
+#include <soc/addressmap.h>
+
#define MVMAP2315_BCM_GICC_EN0 BIT(0)
#define MVMAP2315_BCM_GICD_FIQ_EN BIT(3)
struct mvmap2315_bcm_gicc_regs {
diff --git a/src/soc/marvell/mvmap2315/include/soc/ipc.h b/src/soc/marvell/mvmap2315/include/soc/ipc.h
new file mode 100644
index 0000000..85b1d88
--- /dev/null
+++ b/src/soc/marvell/mvmap2315/include/soc/ipc.h
@@ -0,0 +1,115 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Marvell, Inc.
+ *
+ * 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
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOC_MARVELL_MVMAP2315_IPC_H__
+#define __SOC_MARVELL_MVMAP2315_IPC_H__
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <types.h>
+
+#include <soc/addressmap.h>
+
+#define MVMAP2315_IPC_MSG_BUFFER_OFFSET 0xCE000000
+#define MVMAP2315_IPC_MSG_IRQ_SENT BIT(0)
+#define MVMAP2315_IPC_MSG_IRQ_RECEIVED BIT(0)
+#define MVMAP2315_IPC_MSG_IRQ_ACK BIT(3)
+#define MVMAP2315_IPC_MSG_IRQ_MCU_MSG BIT(6)
+
+struct ipc_mcu_hash_msg {
+ u8 protocol_version;
+ u8 checksum;
+ u16 command_id;
+ u8 command_version;
+ u8 reserved;
+ u16 length;
+ u8 hash_subcommand;
+ u8 hash_type;
+ u8 nonce_size;
+ u8 reserved0;
+ u32 offset;
+ u32 size;
+ u8 nonce_data[64];
+};
+
+struct ipc_mcu_power_msg {
+ u8 protocol_version;
+ u8 checksum;
+ u16 command_id;
+ u8 command_version;
+ u8 reserved;
+ u16 length;
+ u8 power_status;
+};
+
+struct ipc_mcu_hash_reply_msg {
+ u8 protocol_version;
+ u8 checksum;
+ u16 result;
+ u16 length;
+ u8 status;
+ u8 type;
+ u8 digest_size;
+ u8 reserved0;
+ u32 offset;
+ u32 size;
+ u8 digest_data[64];
+};
+
+struct mvmap2315_ipc_regs {
+ u32 ipc_isrr;
+ u32 ipc_wdr_0;
+ u32 ipc_wdr_1;
+ u32 ipc_isrw;
+ u32 ipc_icr;
+ u32 ipc_iir;
+ u32 ipc_rdr_0;
+ u32 ipc_rdr_1;
+ u32 ipc_maj_mid_rev;
+ u32 ipc_cfg_rev;
+ u32 ipc_dummy;
+};
+
+check_member(mvmap2315_ipc_regs, ipc_dummy, 0x28);
+static struct mvmap2315_ipc_regs * const mvmap2315_ipc_sp
+ = (void *)MVMAP2315_IPC_SP_BASE;
+static struct mvmap2315_ipc_regs * const mvmap2315_ipc_mcu
+ = (void *)MVMAP2315_IPC_MCU_BASE;
+enum hash_responses {
+ ABORT = 0x0,
+ FINISHED = 0x1,
+ BUSY = 0x2
+};
+
+enum hash_subcommands {
+ GET_HASH = 0x0,
+ ABORT_HASH = 0x1,
+ START_HASH = 0x2,
+ SYNC_HASH = 0x3
+};
+
+enum msg_types {
+ MSG_READY = 1,
+ MSG_RECEIVED = 8,
+ MSG_READY_RECEIVED = 9,
+};
+
+u8 checksum8(u8 *addr, u32 length);
+void wait_for_ipc_msg(void);
+void *extract_ipc_msg(void);
+void send_ipc_msg(u32 msg_buffer_addr, u32 size);
+int ipc_mcu_hash_msg_cmd(u8 subcommand);
+
+#endif /* __SOC_MARVELL_MVMAP2315_IPC_H__ */
diff --git a/src/soc/marvell/mvmap2315/ipc.c b/src/soc/marvell/mvmap2315/ipc.c
new file mode 100644
index 0000000..81d5a6c
--- /dev/null
+++ b/src/soc/marvell/mvmap2315/ipc.c
@@ -0,0 +1,151 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Marvell, Inc.
+ *
+ * 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
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <soc/gic.h>
+#include <soc/ipc.h>
+#include <string.h>
+
+u8 checksum8(u8 *addr, u32 length)
+{
+ u8 checksum = 0;
+
+ while (length) {
+ checksum += *addr;
+ addr++;
+ --length;
+ }
+ return ~checksum + 1;
+}
+
+void wait_for_ipc_msg(void)
+{
+ while (!(read32(&mvmap2315_bcm_gicd->ispendr2) &
+ MVMAP2315_IPC_MSG_IRQ_MCU_MSG))
+ ;
+
+ printk(BIOS_DEBUG, "MCU msg IRQ Found\n");
+}
+
+void *extract_ipc_msg(void)
+{
+ u32 iir;
+ u32 msg_buffer;
+ u32 reg;
+
+ write32(&mvmap2315_ipc_sp->ipc_dummy, 0xA5A5A5A5);
+
+ iir = read32(&mvmap2315_ipc_sp->ipc_iir);
+ printk(BIOS_DEBUG, "MCU msg IIR is: %d\n", iir);
+
+ switch (iir) {
+ case MSG_READY:
+
+ msg_buffer = read32(&mvmap2315_ipc_sp->ipc_rdr_0)
+ + MVMAP2315_IPC_MSG_BUFFER_OFFSET;
+
+ reg = read32(&mvmap2315_ipc_sp->ipc_icr);
+ reg |= MVMAP2315_IPC_MSG_IRQ_RECEIVED;
+ write32(&mvmap2315_ipc_sp->ipc_icr, reg);
+
+ reg = read32(&mvmap2315_ipc_sp->ipc_isrw);
+ reg |= MVMAP2315_IPC_MSG_IRQ_ACK;
+ write32(&mvmap2315_ipc_sp->ipc_isrw, reg);
+
+ break;
+
+ case MSG_RECEIVED:
+
+ msg_buffer = 0;
+
+ reg = read32(&mvmap2315_ipc_sp->ipc_icr);
+ reg |= MVMAP2315_IPC_MSG_IRQ_ACK;
+ write32(&mvmap2315_ipc_sp->ipc_icr, reg);
+
+ break;
+
+ case MSG_READY_RECEIVED:
+
+ msg_buffer = read32(&mvmap2315_ipc_sp->ipc_rdr_0)
+ + MVMAP2315_IPC_MSG_BUFFER_OFFSET;
+
+ reg = read32(&mvmap2315_ipc_sp->ipc_icr);
+ reg |= (MVMAP2315_IPC_MSG_IRQ_ACK |
+ MVMAP2315_IPC_MSG_IRQ_RECEIVED);
+ write32(&mvmap2315_ipc_sp->ipc_icr, reg);
+
+ reg = read32(&mvmap2315_ipc_sp->ipc_isrw);
+ reg |= MVMAP2315_IPC_MSG_IRQ_ACK;
+ write32(&mvmap2315_ipc_sp->ipc_isrw, reg);
+
+ break;
+
+ default:
+ write32(&mvmap2315_ipc_sp->ipc_iir, iir);
+
+ break;
+ }
+
+ return (void *)msg_buffer;
+}
+
+void send_ipc_msg(u32 msg_buffer_addr, u32 size)
+{
+ u32 reg;
+
+ write32(&mvmap2315_ipc_sp->ipc_wdr_0, msg_buffer_addr);
+
+ reg = read32(&mvmap2315_ipc_sp->ipc_isrw);
+ reg |= MVMAP2315_IPC_MSG_IRQ_SENT;
+ write32(&mvmap2315_ipc_sp->ipc_isrw, reg);
+}
+
+int ipc_mcu_hash_msg_cmd(u8 subcommand)
+{
+ struct ipc_mcu_hash_msg *mcu_hash_msg
+ = (void *)MVMAP2315_IPC_BUFFER_MCU_BASE;
+ struct ipc_mcu_hash_reply_msg *mcu_hash_reply_msg;
+ u32 *ipc_buff;
+
+ /* setting hash msg parameters */
+ mcu_hash_msg->protocol_version = 0x3;
+ mcu_hash_msg->command_id = 0x2A;
+ mcu_hash_msg->reserved = 0x0;
+ mcu_hash_msg->length = 76;
+ mcu_hash_msg->checksum = 0;
+ mcu_hash_msg->hash_subcommand = subcommand;
+ mcu_hash_msg->hash_type = 0;
+ mcu_hash_msg->nonce_size = 0;
+ mcu_hash_msg->reserved0 = 0;
+ mcu_hash_msg->offset = 0;
+ mcu_hash_msg->size = 32;
+ mcu_hash_msg->checksum = checksum8((u8 *)mcu_hash_msg,
+ sizeof(struct ipc_mcu_hash_msg));
+
+ send_ipc_msg((u32)mcu_hash_msg, sizeof(struct ipc_mcu_hash_msg));
+
+ wait_for_ipc_msg();
+
+ ipc_buff = extract_ipc_msg();
+
+ mcu_hash_reply_msg = (void *)ipc_buff;
+
+ wait_for_ipc_msg();
+
+ ipc_buff = extract_ipc_msg();
+
+ return mcu_hash_reply_msg->status;
+}
diff --git a/src/soc/marvell/mvmap2315/power.c b/src/soc/marvell/mvmap2315/power.c
index 772715d..dd71b9b 100644
--- a/src/soc/marvell/mvmap2315/power.c
+++ b/src/soc/marvell/mvmap2315/power.c
@@ -21,6 +21,7 @@
#include <soc/clock.h>
#include <soc/power.h>
#include <soc/pwr_types.h>
+#include <soc/ipc.h>
static void enable_sys_power(void)
{
@@ -126,5 +127,14 @@ void full_boot(void)
u32 get_boot_path(void)
{
- return FULL_BOOT;
+ struct ipc_mcu_power_msg *power_status_msg;
+ u32 *ipc_buff;
+
+ wait_for_ipc_msg();
+
+ ipc_buff = extract_ipc_msg();
+
+ power_status_msg = (void *)ipc_buff;
+
+ return power_status_msg->power_status;
}
diff --git a/src/soc/marvell/mvmap2315/romstage.c b/src/soc/marvell/mvmap2315/romstage.c
index 0e32020..7d84651 100644
--- a/src/soc/marvell/mvmap2315/romstage.c
+++ b/src/soc/marvell/mvmap2315/romstage.c
@@ -24,6 +24,7 @@
#include <soc/bootrom.h>
#include <soc/clock.h>
#include <soc/gic.h>
+#include <soc/ipc.h>
#include <soc/monotonic_timer.h>
#include <soc/power.h>
#include <soc/romstage.h>
@@ -82,13 +83,15 @@ void main(void)
printk(BIOS_INFO, "loading and validating MCU FIRMWARE\n");
load_and_validate_image(&bdb_info, MCU_FIRMWARE);
mcu_start();
+ boot_path = get_boot_path();
} else {
printk(BIOS_INFO, "low power restart. skip MCU code load\n");
- printk(BIOS_INFO, "TODO: check MCU Firmware hash\n");
+ printk(BIOS_INFO, "checking MCU Firmware hash\n");
+ ipc_mcu_hash_msg_cmd(GET_HASH);
+ printk(BIOS_INFO, "comparison not currently implemented\n");
+ boot_path = get_boot_path();
}
- boot_path = get_boot_path();
-
switch (boot_path) {
case NO_BOOT:
no_boot();
More information about the coreboot-gerrit
mailing list