summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorMarek BehĂșn <marek.behun@nic.cz>2018-12-17 16:10:08 +0100
committerStefan Roese <sr@denx.de>2019-01-21 11:39:50 +0100
commitc87b87006b0d1f42dd0b2f3a2c0a3048959489cf (patch)
tree97b000be4339225bd122fe6d1a054b6431533e0c /board
parentda1f799700ba4fbc9f24bc2dd4871260d14768b9 (diff)
arm: mvebu: turris_mox: Read info (and ethaddrs) from OTP
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 <marek.behun@nic.cz> Reviewed-by: Stefan Roese <sr@denx.de> Signed-off-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'board')
-rw-r--r--board/CZ.NIC/turris_mox/Makefile2
-rw-r--r--board/CZ.NIC/turris_mox/mox_sp.c136
-rw-r--r--board/CZ.NIC/turris_mox/mox_sp.h15
-rw-r--r--board/CZ.NIC/turris_mox/turris_mox.c55
4 files changed, 205 insertions, 3 deletions
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 <marek.behun@nic.cz>
-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..0b29ffcc67
--- /dev/null
+++ b/board/CZ.NIC/turris_mox/mox_sp.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#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_HASH,
+ MBOX_CMD_SIGN,
+ MBOX_CMD_VERIFY,
+
+ MBOX_CMD_OTP_READ,
+ MBOX_CMD_OTP_WRITE
+};
+
+static int mbox_do_cmd(enum mbox_cmd cmd, u32 *out, int nout)
+{
+ const int tries = 50;
+ int i;
+ u32 status;
+
+ clrbits_le32(RWTM_HOST_INT_MASK, SP_CMD_COMPLETE);
+
+ writel(cmd, RWTM_CMD);
+
+ for (i = 0; i < tries; ++i) {
+ mdelay(10);
+ if (readl(RWTM_HOST_INT_RESET) & SP_CMD_COMPLETE)
+ break;
+ }
+
+ if (i == tries) {
+ /* 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 <marek.behun@nic.cz>
+ */
+
+#ifndef _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_
+#define _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_
+
+#include <common.h>
+
+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 4426ee3446..d16d6fd124 100644
--- a/board/CZ.NIC/turris_mox/turris_mox.c
+++ b/board/CZ.NIC/turris_mox/turris_mox.c
@@ -14,11 +14,14 @@
#include <linux/string.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
+#include <environment.h>
#ifdef CONFIG_WDT_ARMADA_37XX
#include <wdt.h>
#endif
+#include "mox_sp.h"
+
#define MAX_MOX_MODULES 10
#define MOX_MODULE_SFP 0x1
@@ -366,6 +369,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 +420,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: