[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