]>
Commit | Line | Data |
---|---|---|
c87b8700 MB |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2018 Marek Behun <[email protected]> | |
4 | */ | |
5 | ||
6 | #include <common.h> | |
96578410 | 7 | #include <asm/arch/soc.h> |
c87b8700 | 8 | #include <asm/io.h> |
c05ed00a | 9 | #include <linux/delay.h> |
c87b8700 | 10 | |
96578410 MB |
11 | #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) | |
c87b8700 | 16 | |
96578410 MB |
17 | #define RWTM_HOST_INT_RESET (RWTM_BASE + 0xc8) |
18 | #define RWTM_HOST_INT_MASK (RWTM_BASE + 0xcc) | |
c87b8700 MB |
19 | #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 | ||
29 | enum 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 | ||
41 | static 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 | ||
79 | const 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 | ||
101 | static 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 | ||
111 | int 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 | } |