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