hakim giydan (hgiydan@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@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@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();