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