blob: 3c23471e6562e25ab0b3b0dba9261b75c552e765 [file] [log] [blame]
Marek Behún35572c92018-12-17 16:10:08 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
4 */
5
6#include <common.h>
Marek Behún1055ce12020-04-08 12:02:07 +02007#include <asm/arch/soc.h>
Marek Behún35572c92018-12-17 16:10:08 +01008#include <asm/io.h>
9
Marek Behún1055ce12020-04-08 12:02:07 +020010#define RWTM_BASE (MVEBU_REGISTER(0xb0000))
11#define RWTM_CMD_PARAM(i) (size_t)(RWTM_BASE + (i) * 4)
12#define RWTM_CMD (RWTM_BASE + 0x40)
13#define RWTM_CMD_RETSTATUS (RWTM_BASE + 0x80)
14#define RWTM_CMD_STATUS(i) (size_t)(RWTM_BASE + 0x84 + (i) * 4)
Marek Behún35572c92018-12-17 16:10:08 +010015
Marek Behún1055ce12020-04-08 12:02:07 +020016#define RWTM_HOST_INT_RESET (RWTM_BASE + 0xc8)
17#define RWTM_HOST_INT_MASK (RWTM_BASE + 0xcc)
Marek Behún35572c92018-12-17 16:10:08 +010018#define SP_CMD_COMPLETE BIT(0)
19
20#define MBOX_STS_SUCCESS (0x0 << 30)
21#define MBOX_STS_FAIL (0x1 << 30)
22#define MBOX_STS_BADCMD (0x2 << 30)
23#define MBOX_STS_LATER (0x3 << 30)
24#define MBOX_STS_ERROR(s) ((s) & (3 << 30))
25#define MBOX_STS_VALUE(s) (((s) >> 10) & 0xfffff)
26#define MBOX_STS_CMD(s) ((s) & 0x3ff)
27
28enum mbox_cmd {
29 MBOX_CMD_GET_RANDOM = 1,
30 MBOX_CMD_BOARD_INFO,
31 MBOX_CMD_ECDSA_PUB_KEY,
32 MBOX_CMD_HASH,
33 MBOX_CMD_SIGN,
34 MBOX_CMD_VERIFY,
35
36 MBOX_CMD_OTP_READ,
37 MBOX_CMD_OTP_WRITE
38};
39
40static int mbox_do_cmd(enum mbox_cmd cmd, u32 *out, int nout)
41{
42 const int tries = 50;
43 int i;
44 u32 status;
45
46 clrbits_le32(RWTM_HOST_INT_MASK, SP_CMD_COMPLETE);
47
48 writel(cmd, RWTM_CMD);
49
50 for (i = 0; i < tries; ++i) {
51 mdelay(10);
52 if (readl(RWTM_HOST_INT_RESET) & SP_CMD_COMPLETE)
53 break;
54 }
55
56 if (i == tries) {
57 /* if timed out, don't read status */
58 setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE);
59 return -ETIMEDOUT;
60 }
61
62 for (i = 0; i < nout; ++i)
63 out[i] = readl(RWTM_CMD_STATUS(i));
64 status = readl(RWTM_CMD_RETSTATUS);
65
66 setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE);
67
68 if (MBOX_STS_CMD(status) != cmd)
69 return -EIO;
70 else if (MBOX_STS_ERROR(status) == MBOX_STS_FAIL)
71 return -(int)MBOX_STS_VALUE(status);
72 else if (MBOX_STS_ERROR(status) != MBOX_STS_SUCCESS)
73 return -EIO;
74 else
75 return MBOX_STS_VALUE(status);
76}
77
78const char *mox_sp_get_ecdsa_public_key(void)
79{
80 static char public_key[135];
81 u32 out[16];
82 int res;
83
84 if (public_key[0])
85 return public_key;
86
87 res = mbox_do_cmd(MBOX_CMD_ECDSA_PUB_KEY, out, 16);
88 if (res < 0)
89 return NULL;
90
91 sprintf(public_key,
92 "%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
93 (u32)res, out[0], out[1], out[2], out[3], out[4], out[5],
94 out[6], out[7], out[8], out[9], out[10], out[11], out[12],
95 out[13], out[14], out[15]);
96
97 return public_key;
98}
99
100static inline void res_to_mac(u8 *mac, u32 t1, u32 t2)
101{
102 mac[0] = t1 >> 8;
103 mac[1] = t1;
104 mac[2] = t2 >> 24;
105 mac[3] = t2 >> 16;
106 mac[4] = t2 >> 8;
107 mac[5] = t2;
108}
109
110int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv, int *ram)
111{
112 u32 out[8];
113 int res;
114
115 res = mbox_do_cmd(MBOX_CMD_BOARD_INFO, out, 8);
116 if (res < 0)
117 return res;
118
119 if (sn) {
120 *sn = out[1];
121 *sn <<= 32;
122 *sn |= out[0];
123 }
124
125 if (bv)
126 *bv = out[2];
127
128 if (ram)
129 *ram = out[3];
130
131 if (mac1)
132 res_to_mac(mac1, out[4], out[5]);
133
134 if (mac2)
135 res_to_mac(mac2, out[6], out[7]);
136
137 return 0;
138}