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