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