From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stefan Roese Date: Thu, 29 Nov 2018 14:04:18 +0100 Subject: [U-Boot] [PATCH u-boot-marvell v3 08/10] board: turris_mox: Read info (and ethaddrs) from OTP In-Reply-To: <20181120120409.12822-8-marek.behun@nic.cz> References: <20181120120409.12822-1-marek.behun@nic.cz> <20181120120409.12822-8-marek.behun@nic.cz> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit To: u-boot@lists.denx.de On 20.11.18 13:04, Marek Behún wrote: > Add support for reading One-Time Programmable memory via mailbox, which > communicates with CZ.NIC's firmware on the Secure Processor (Cortex-M3) > of Armada 3720. > > Display product serial number and additional info, and also set MAC > addresses. > > Signed-off-by: Marek Behún Reviewed-by: Stefan Roese Thanks, Stefan > --- > board/CZ.NIC/turris_mox/Makefile | 2 +- > board/CZ.NIC/turris_mox/mox_sp.c | 133 +++++++++++++++++++++++++++ > board/CZ.NIC/turris_mox/mox_sp.h | 15 +++ > board/CZ.NIC/turris_mox/turris_mox.c | 54 ++++++++++- > 4 files changed, 201 insertions(+), 3 deletions(-) > create mode 100644 board/CZ.NIC/turris_mox/mox_sp.c > create mode 100644 board/CZ.NIC/turris_mox/mox_sp.h > > diff --git a/board/CZ.NIC/turris_mox/Makefile b/board/CZ.NIC/turris_mox/Makefile > index 619704288b..33a52b63d7 100644 > --- a/board/CZ.NIC/turris_mox/Makefile > +++ b/board/CZ.NIC/turris_mox/Makefile > @@ -2,4 +2,4 @@ > # > # Copyright (C) 2018 Marek Behun > > -obj-y := turris_mox.o > +obj-y := turris_mox.o mox_sp.o > diff --git a/board/CZ.NIC/turris_mox/mox_sp.c b/board/CZ.NIC/turris_mox/mox_sp.c > new file mode 100644 > index 0000000000..78438227dc > --- /dev/null > +++ b/board/CZ.NIC/turris_mox/mox_sp.c > @@ -0,0 +1,133 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (C) 2018 Marek Behun > + */ > + > +#include > +#include > + > +#define RWTM_CMD_PARAM(i) (size_t)(0xd00b0000 + (i) * 4) > +#define RWTM_CMD 0xd00b0040 > +#define RWTM_CMD_RETSTATUS 0xd00b0080 > +#define RWTM_CMD_STATUS(i) (size_t)(0xd00b0084 + (i) * 4) > + > +#define RWTM_HOST_INT_RESET 0xd00b00c8 > +#define RWTM_HOST_INT_MASK 0xd00b00cc > +#define SP_CMD_COMPLETE BIT(0) > + > +#define MBOX_STS_SUCCESS (0x0 << 30) > +#define MBOX_STS_FAIL (0x1 << 30) > +#define MBOX_STS_BADCMD (0x2 << 30) > +#define MBOX_STS_LATER (0x3 << 30) > +#define MBOX_STS_ERROR(s) ((s) & (3 << 30)) > +#define MBOX_STS_VALUE(s) (((s) >> 10) & 0xfffff) > +#define MBOX_STS_CMD(s) ((s) & 0x3ff) > + > +enum mbox_cmd { > + MBOX_CMD_GET_RANDOM = 1, > + MBOX_CMD_BOARD_INFO, > + MBOX_CMD_ECDSA_PUB_KEY, > + MBOX_CMD_ECDSA_SIGN, > + > + MBOX_CMD_OTP_READ, > + MBOX_CMD_OTP_WRITE > +}; > + > +static int mbox_do_cmd(enum mbox_cmd cmd, u32 *out, int nout) > +{ > + int i; > + u32 status; > + > + clrbits_le32(RWTM_HOST_INT_MASK, SP_CMD_COMPLETE); > + > + writel(cmd, RWTM_CMD); > + > + for (i = 0; i < 10; ++i) { > + mdelay(10); > + if (readl(RWTM_HOST_INT_RESET) & SP_CMD_COMPLETE) > + break; > + } > + > + if (i == 10) { > + /* if timed out, don't read status */ > + setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE); > + return -ETIMEDOUT; > + } > + > + for (i = 0; i < nout; ++i) > + out[i] = readl(RWTM_CMD_STATUS(i)); > + status = readl(RWTM_CMD_RETSTATUS); > + > + setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE); > + > + if (MBOX_STS_CMD(status) != cmd) > + return -EIO; > + else if (MBOX_STS_ERROR(status) == MBOX_STS_FAIL) > + return -(int)MBOX_STS_VALUE(status); > + else if (MBOX_STS_ERROR(status) != MBOX_STS_SUCCESS) > + return -EIO; > + else > + return MBOX_STS_VALUE(status); > +} > + > +const char *mox_sp_get_ecdsa_public_key(void) > +{ > + static char public_key[135]; > + u32 out[16]; > + int res; > + > + if (public_key[0]) > + return public_key; > + > + res = mbox_do_cmd(MBOX_CMD_ECDSA_PUB_KEY, out, 16); > + if (res < 0) > + return NULL; > + > + sprintf(public_key, > + "%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", > + (u32)res, out[0], out[1], out[2], out[3], out[4], out[5], > + out[6], out[7], out[8], out[9], out[10], out[11], out[12], > + out[13], out[14], out[15]); > + > + return public_key; > +} > + > +static inline void res_to_mac(u8 *mac, u32 t1, u32 t2) > +{ > + mac[0] = t1 >> 8; > + mac[1] = t1; > + mac[2] = t2 >> 24; > + mac[3] = t2 >> 16; > + mac[4] = t2 >> 8; > + mac[5] = t2; > +} > + > +int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv, int *ram) > +{ > + u32 out[8]; > + int res; > + > + res = mbox_do_cmd(MBOX_CMD_BOARD_INFO, out, 8); > + if (res < 0) > + return res; > + > + if (sn) { > + *sn = out[1]; > + *sn <<= 32; > + *sn |= out[0]; > + } > + > + if (bv) > + *bv = out[2]; > + > + if (ram) > + *ram = out[3]; > + > + if (mac1) > + res_to_mac(mac1, out[4], out[5]); > + > + if (mac2) > + res_to_mac(mac2, out[6], out[7]); > + > + return 0; > +} > diff --git a/board/CZ.NIC/turris_mox/mox_sp.h b/board/CZ.NIC/turris_mox/mox_sp.h > new file mode 100644 > index 0000000000..49a4ed80ea > --- /dev/null > +++ b/board/CZ.NIC/turris_mox/mox_sp.h > @@ -0,0 +1,15 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * Copyright (C) 2018 Marek Behun > + */ > + > +#ifndef _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_ > +#define _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_ > + > +#include > + > +const char *mox_sp_get_ecdsa_public_key(void); > +int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv, > + int *ram); > + > +#endif /* _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_ */ > diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c > index 39c26416a7..89b3cd2ce0 100644 > --- a/board/CZ.NIC/turris_mox/turris_mox.c > +++ b/board/CZ.NIC/turris_mox/turris_mox.c > @@ -19,6 +19,8 @@ > #include > #endif > > +#include "mox_sp.h" > + > #define MAX_MOX_MODULES 10 > > #define MOX_MODULE_SFP 0x1 > @@ -366,6 +368,49 @@ static int get_reset_gpio(struct gpio_desc *reset_gpio) > return 0; > } > > +int misc_init_r(void) > +{ > + int ret; > + u8 mac1[6], mac2[6]; > + > + ret = mbox_sp_get_board_info(NULL, mac1, mac2, NULL, NULL); > + if (ret < 0) { > + printf("Cannot read data from OTP!\n"); > + return 0; > + } > + > + if (is_valid_ethaddr(mac1) && !env_get("ethaddr")) > + eth_env_set_enetaddr("ethaddr", mac1); > + > + if (is_valid_ethaddr(mac2) && !env_get("eth1addr")) > + eth_env_set_enetaddr("eth1addr", mac2); > + > + return 0; > +} > + > +static void mox_print_info(void) > +{ > + int ret, board_version, ram_size; > + u64 serial_number; > + const char *pub_key; > + > + ret = mbox_sp_get_board_info(&serial_number, NULL, NULL, &board_version, > + &ram_size); > + if (ret < 0) > + return; > + > + printf("Turris Mox:\n"); > + printf(" Board version: %i\n", board_version); > + printf(" RAM size: %i MiB\n", ram_size); > + printf(" Serial Number: %016llX\n", serial_number); > + > + pub_key = mox_sp_get_ecdsa_public_key(); > + if (pub_key) > + printf(" ECDSA Public Key: %s\n", pub_key); > + else > + printf("Cannot read ECDSA Public Key\n"); > +} > + > int last_stage_init(void) > { > int ret, i; > @@ -374,14 +419,19 @@ int last_stage_init(void) > struct mii_dev *bus; > struct gpio_desc reset_gpio = {}; > > + mox_print_info(); > + > ret = mox_get_topology(&topology, &module_count, &is_sd); > if (ret) { > printf("Cannot read module topology!\n"); > return 0; > } > > - printf("Found Turris Mox %s version\n", is_sd ? "SD" : "eMMC"); > - printf("Module Topology:\n"); > + printf(" SD/eMMC version: %s\n", is_sd ? "SD" : "eMMC"); > + > + if (module_count) > + printf("Module Topology:\n"); > + > for (i = 0; i < module_count; ++i) { > switch (topology[i]) { > case MOX_MODULE_SFP: > Viele Grüße, Stefan -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de