1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <clk.h> 8 #include <crypto.h> 9 #include <dm.h> 10 #include <rockchip/crypto_v1.h> 11 #include <asm/io.h> 12 #include <asm/arch/hardware.h> 13 #include <asm/arch/clock.h> 14 15 #define CRYPTO_V1_DEFAULT_RATE 100000000 16 17 struct rockchip_crypto_priv { 18 struct rk_crypto_reg *reg; 19 struct clk clk; 20 u32 frequency; 21 char *clocks; 22 u32 nclocks; 23 u32 length; 24 }; 25 26 static u32 rockchip_crypto_capability(struct udevice *dev) 27 { 28 return CRYPTO_MD5 | 29 CRYPTO_SHA1 | 30 CRYPTO_SHA256 | 31 CRYPTO_RSA512 | 32 CRYPTO_RSA1024 | 33 CRYPTO_RSA2048; 34 } 35 36 static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx) 37 { 38 struct rockchip_crypto_priv *priv = dev_get_priv(dev); 39 struct rk_crypto_reg *reg = priv->reg; 40 u32 val; 41 42 if (!ctx || !ctx->length) 43 return -EINVAL; 44 45 priv->length = 0; 46 writel(ctx->length, ®->crypto_hash_msg_len); 47 if (ctx->algo == CRYPTO_SHA256) { 48 /* Set SHA256 mode and out byte swap */ 49 writel(HASH_SWAP_DO | ENGINE_SELECTION_SHA256, 50 ®->crypto_hash_ctrl); 51 52 val = readl(®->crypto_conf); 53 val &= ~BYTESWAP_HRFIFO; 54 writel(val, ®->crypto_conf); 55 } else if (ctx->algo == CRYPTO_SHA1) { 56 /* Set SHA160 input byte swap */ 57 val = readl(®->crypto_conf); 58 val |= BYTESWAP_HRFIFO; 59 writel(val, ®->crypto_conf); 60 61 /* Set SHA160 mode and out byte swap */ 62 writel(HASH_SWAP_DO, ®->crypto_hash_ctrl); 63 } else if (ctx->algo == CRYPTO_MD5) { 64 /* Set MD5 input byte swap */ 65 val = readl(®->crypto_conf); 66 val |= BYTESWAP_HRFIFO; 67 writel(val, ®->crypto_conf); 68 69 /* Set MD5 mode and out byte swap */ 70 writel(HASH_SWAP_DO | ENGINE_SELECTION_MD5, 71 ®->crypto_hash_ctrl); 72 } else { 73 return -EINVAL; 74 } 75 76 rk_setreg(®->crypto_ctrl, HASH_FLUSH); 77 do {} while (readl(®->crypto_ctrl) & HASH_FLUSH); 78 79 /* SHA256 needs input byte swap */ 80 if (ctx->algo == CRYPTO_SHA256) { 81 val = readl(®->crypto_conf); 82 val |= BYTESWAP_HRFIFO; 83 writel(val, ®->crypto_conf); 84 } 85 86 return 0; 87 } 88 89 static int rockchip_crypto_sha_update(struct udevice *dev, 90 u32 *input, u32 len) 91 { 92 struct rockchip_crypto_priv *priv = dev_get_priv(dev); 93 struct rk_crypto_reg *reg = priv->reg; 94 95 if (!len) 96 return -EINVAL; 97 98 priv->length += len; 99 100 /* Must flush dcache before crypto DMA fetch data region */ 101 flush_cache((unsigned long)input, len); 102 103 /* Wait last complete */ 104 do {} while (readl(®->crypto_ctrl) & HASH_START); 105 106 /* Hash Done Interrupt */ 107 writel(HASH_DONE_INT, ®->crypto_intsts); 108 109 /* Set data base and length */ 110 writel((u32)(ulong)input, ®->crypto_hrdmas); 111 writel((len + 3) >> 2, ®->crypto_hrdmal); 112 113 /* Write 1 to start. When finishes, the core will clear it */ 114 rk_setreg(®->crypto_ctrl, HASH_START); 115 116 return 0; 117 } 118 119 static int rockchip_crypto_sha_final(struct udevice *dev, 120 sha_context *ctx, u8 *output) 121 { 122 struct rockchip_crypto_priv *priv = dev_get_priv(dev); 123 struct rk_crypto_reg *reg = priv->reg; 124 u32 *buf = (u32 *)output; 125 u32 nbits; 126 int i; 127 128 if (priv->length != ctx->length) { 129 printf("%s: Err: update total length(0x%x) is not equal " 130 "to init total length(0x%x)!\n", 131 __func__, priv->length, ctx->length); 132 return -EIO; 133 } 134 135 /* Wait last complete */ 136 do {} while (readl(®->crypto_ctrl) & HASH_START); 137 138 /* It is high when finish, and it will not be low until it restart */ 139 do {} while (!readl(®->crypto_hash_sts)); 140 141 /* Read hash data, per-data 32-bit */ 142 nbits = crypto_algo_nbits(ctx->algo); 143 for (i = 0; i < BYTE2WORD(nbits); i++) 144 buf[i] = readl(®->crypto_hash_dout[i]); 145 146 return 0; 147 } 148 149 static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, 150 u8 *sign, u8 *output) 151 { 152 struct rockchip_crypto_priv *priv = dev_get_priv(dev); 153 struct rk_crypto_reg *reg = priv->reg; 154 u32 nbits, *buf = (u32 *)output; 155 int i, value; 156 157 if (!ctx) 158 return -EINVAL; 159 160 if (ctx->algo == CRYPTO_RSA512) 161 value = PKA_BLOCK_SIZE_512; 162 else if (ctx->algo == CRYPTO_RSA1024) 163 value = PKA_BLOCK_SIZE_1024; 164 else if (ctx->algo == CRYPTO_RSA2048) 165 value = PKA_BLOCK_SIZE_2048; 166 else 167 return -EINVAL; 168 169 /* Specify the nbits of N in PKA calculation */ 170 writel(value, ®->crypto_pka_ctrl); 171 172 /* Flush SHA and RSA */ 173 rk_setreg(®->crypto_ctrl, PKA_HASH_CTRL); 174 writel(0xffffffff, ®->crypto_intsts); 175 do {} while (readl(®->crypto_ctrl) & PKA_CTRL); 176 177 /* Clean PKA done interrupt */ 178 writel(PKA_DONE_INT, ®->crypto_intsts); 179 180 /* Set m/n/e/c */ 181 nbits = crypto_algo_nbits(ctx->algo); 182 memcpy((void *)®->crypto_pka_m, (void *)sign, BITS2BYTE(nbits)); 183 memcpy((void *)®->crypto_pka_n, (void *)ctx->n, BITS2BYTE(nbits)); 184 memcpy((void *)®->crypto_pka_e, (void *)ctx->e, BITS2BYTE(nbits)); 185 memcpy((void *)®->crypto_pka_c, (void *)ctx->c, BITS2BYTE(nbits)); 186 do {} while (readl(®->crypto_ctrl) & PKA_START); 187 188 /* Start PKA */ 189 rk_setreg(®->crypto_ctrl, PKA_START); 190 191 /* Wait PKA done */ 192 do {} while (readl(®->crypto_ctrl) & PKA_START); 193 194 /* Read hash data, per-data 32-bit */ 195 for (i = 0; i < BITS2WORD(nbits); i++) 196 buf[i] = readl(®->crypto_pka_m[i]); 197 198 return 0; 199 } 200 201 static const struct dm_crypto_ops rockchip_crypto_ops = { 202 .capability = rockchip_crypto_capability, 203 .sha_init = rockchip_crypto_sha_init, 204 .sha_update = rockchip_crypto_sha_update, 205 .sha_final = rockchip_crypto_sha_final, 206 .rsa_verify = rockchip_crypto_rsa_verify, 207 }; 208 209 /* 210 * Only use "clocks" to parse crypto clock id and use rockchip_get_clk(). 211 * Because we always add crypto node in U-Boot dts, when kernel dtb enabled : 212 * 213 * 1. There is cru phandle mismatch between U-Boot and kernel dtb; 214 * 2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property; 215 */ 216 static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev) 217 { 218 struct rockchip_crypto_priv *priv = dev_get_priv(dev); 219 int len; 220 221 if (!dev_read_prop(dev, "clocks", &len)) { 222 printf("Can't find \"clocks\" property\n"); 223 return -EINVAL; 224 } 225 226 priv->clocks = malloc(len); 227 if (!priv->clocks) 228 return -ENOMEM; 229 230 priv->nclocks = len / sizeof(u32); 231 if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks, 232 priv->nclocks)) { 233 printf("Can't read \"clocks\" property\n"); 234 return -EINVAL; 235 } 236 237 priv->reg = dev_read_addr_ptr(dev); 238 priv->frequency = dev_read_u32_default(dev, "clock-frequency", 239 CRYPTO_V1_DEFAULT_RATE); 240 241 return 0; 242 } 243 244 static int rockchip_crypto_probe(struct udevice *dev) 245 { 246 struct rockchip_crypto_priv *priv = dev_get_priv(dev); 247 u32 *clocks; 248 int i, ret; 249 250 ret = rockchip_get_clk(&priv->clk.dev); 251 if (ret) { 252 printf("Failed to get clk device, ret=%d\n", ret); 253 return ret; 254 } 255 256 clocks = (u32 *)priv->clocks; 257 for (i = 1; i < priv->nclocks; i += 2) { 258 priv->clk.id = clocks[i]; 259 ret = clk_set_rate(&priv->clk, priv->frequency); 260 if (ret < 0) { 261 printf("%s: Failed to set clk(%ld): ret=%d\n", 262 __func__, priv->clk.id, ret); 263 return ret; 264 } 265 } 266 267 return 0; 268 } 269 270 static const struct udevice_id rockchip_crypto_ids[] = { 271 { .compatible = "rockchip,rk3399-crypto" }, 272 { .compatible = "rockchip,rk3368-crypto" }, 273 { .compatible = "rockchip,rk3328-crypto" }, 274 { .compatible = "rockchip,rk3288-crypto" }, 275 { .compatible = "rockchip,rk322x-crypto" }, 276 { .compatible = "rockchip,rk312x-crypto" }, 277 { } 278 }; 279 280 U_BOOT_DRIVER(rockchip_crypto_v1) = { 281 .name = "rockchip_crypto_v1", 282 .id = UCLASS_CRYPTO, 283 .of_match = rockchip_crypto_ids, 284 .ops = &rockchip_crypto_ops, 285 .probe = rockchip_crypto_probe, 286 .ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata, 287 .priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv), 288 }; 289