1e31caa5aSChia-Wei Wang // SPDX-License-Identifier: GPL-2.0-or-later 2e31caa5aSChia-Wei Wang /* 3e31caa5aSChia-Wei Wang * (C) Copyright ASPEED Technology Inc. 4e31caa5aSChia-Wei Wang * Copyright 2021 IBM Corp. 5e31caa5aSChia-Wei Wang */ 6e31caa5aSChia-Wei Wang #include <common.h> 7e31caa5aSChia-Wei Wang #include <clk.h> 8e31caa5aSChia-Wei Wang 9e31caa5aSChia-Wei Wang #include <log.h> 10e31caa5aSChia-Wei Wang #include <asm/io.h> 11e31caa5aSChia-Wei Wang #include <malloc.h> 12e31caa5aSChia-Wei Wang #include <hash.h> 13e31caa5aSChia-Wei Wang 14e31caa5aSChia-Wei Wang #include <dm/device.h> 15e31caa5aSChia-Wei Wang #include <dm/fdtaddr.h> 16e31caa5aSChia-Wei Wang 17e31caa5aSChia-Wei Wang #include <linux/bitops.h> 18e31caa5aSChia-Wei Wang #include <linux/delay.h> 19e31caa5aSChia-Wei Wang #include <linux/kernel.h> 20e31caa5aSChia-Wei Wang #include <linux/iopoll.h> 21e31caa5aSChia-Wei Wang 22e31caa5aSChia-Wei Wang #define ASPEED_HACE_STS 0x1C 23e31caa5aSChia-Wei Wang #define HACE_RSA_ISR BIT(13) 24e31caa5aSChia-Wei Wang #define HACE_CRYPTO_ISR BIT(12) 25e31caa5aSChia-Wei Wang #define HACE_HASH_ISR BIT(9) 26e31caa5aSChia-Wei Wang #define HACE_RSA_BUSY BIT(2) 27e31caa5aSChia-Wei Wang #define HACE_CRYPTO_BUSY BIT(1) 28e31caa5aSChia-Wei Wang #define HACE_HASH_BUSY BIT(0) 29e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_SRC 0x20 30e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_DIGEST_BUFF 0x24 31e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_KEY_BUFF 0x28 32e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_DATA_LEN 0x2C 33e31caa5aSChia-Wei Wang #define HACE_SG_LAST BIT(31) 34e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_CMD 0x30 35e31caa5aSChia-Wei Wang #define HACE_SHA_BE_EN BIT(3) 36e31caa5aSChia-Wei Wang #define HACE_MD5_LE_EN BIT(2) 37e31caa5aSChia-Wei Wang #define HACE_ALGO_MD5 0 38e31caa5aSChia-Wei Wang #define HACE_ALGO_SHA1 BIT(5) 39e31caa5aSChia-Wei Wang #define HACE_ALGO_SHA224 BIT(6) 40e31caa5aSChia-Wei Wang #define HACE_ALGO_SHA256 (BIT(4) | BIT(6)) 41e31caa5aSChia-Wei Wang #define HACE_ALGO_SHA512 (BIT(5) | BIT(6)) 42e31caa5aSChia-Wei Wang #define HACE_ALGO_SHA384 (BIT(5) | BIT(6) | BIT(10)) 43*ebf0f73fSJohnny Huang #define HASH_CMD_ACC_MODE (0x2 << 7) 44e31caa5aSChia-Wei Wang #define HACE_SG_EN BIT(18) 45e31caa5aSChia-Wei Wang 46*ebf0f73fSJohnny Huang #define ASPEED_SHA1_DIGEST_SIZE 20 47*ebf0f73fSJohnny Huang #define ASPEED_SHA256_DIGEST_SIZE 32 48*ebf0f73fSJohnny Huang #define ASPEED_SHA384_DIGEST_SIZE 64 49*ebf0f73fSJohnny Huang #define ASPEED_SHA512_DIGEST_SIZE 64 50*ebf0f73fSJohnny Huang 51*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA1 1 52*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA256 2 53*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA384 3 54*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA512 4 55e31caa5aSChia-Wei Wang 56e31caa5aSChia-Wei Wang struct aspeed_sg { 57e31caa5aSChia-Wei Wang u32 len; 58e31caa5aSChia-Wei Wang u32 addr; 59e31caa5aSChia-Wei Wang }; 60e31caa5aSChia-Wei Wang 61e31caa5aSChia-Wei Wang struct aspeed_hash_ctx { 62*ebf0f73fSJohnny Huang struct aspeed_sg sg[2]; /* Must be 8 byte aligned */ 63*ebf0f73fSJohnny Huang u8 digest[64]; /* Must be 8 byte aligned */ 64e31caa5aSChia-Wei Wang u32 method; 65e31caa5aSChia-Wei Wang u32 digest_size; 66*ebf0f73fSJohnny Huang u32 block_size; 67*ebf0f73fSJohnny Huang u64 digcnt[2]; /* total length */ 68*ebf0f73fSJohnny Huang u32 bufcnt; 69*ebf0f73fSJohnny Huang u8 buffer[256]; 70e31caa5aSChia-Wei Wang }; 71e31caa5aSChia-Wei Wang 72e31caa5aSChia-Wei Wang struct aspeed_hace { 73e31caa5aSChia-Wei Wang struct clk clk; 74e31caa5aSChia-Wei Wang }; 75e31caa5aSChia-Wei Wang 76*ebf0f73fSJohnny Huang static const u32 sha1_iv[8] = { 77*ebf0f73fSJohnny Huang 0x01234567UL, 0x89abcdefUL, 0xfedcba98UL, 0x76543210UL, 78*ebf0f73fSJohnny Huang 0xf0e1d2c3UL, 0, 0, 0 79*ebf0f73fSJohnny Huang }; 80*ebf0f73fSJohnny Huang 81*ebf0f73fSJohnny Huang static const u32 sha256_iv[8] = { 82*ebf0f73fSJohnny Huang 0x67e6096aUL, 0x85ae67bbUL, 0x72f36e3cUL, 0x3af54fa5UL, 83*ebf0f73fSJohnny Huang 0x7f520e51UL, 0x8c68059bUL, 0xabd9831fUL, 0x19cde05bUL 84*ebf0f73fSJohnny Huang }; 85*ebf0f73fSJohnny Huang 86*ebf0f73fSJohnny Huang static const u32 sha384_iv[16] = { 87*ebf0f73fSJohnny Huang 0x5d9dbbcbUL, 0xd89e05c1UL, 0x2a299a62UL, 0x07d57c36UL, 88*ebf0f73fSJohnny Huang 0x5a015991UL, 0x17dd7030UL, 0xd8ec2f15UL, 0x39590ef7UL, 89*ebf0f73fSJohnny Huang 0x67263367UL, 0x310bc0ffUL, 0x874ab48eUL, 0x11155868UL, 90*ebf0f73fSJohnny Huang 0x0d2e0cdbUL, 0xa78ff964UL, 0x1d48b547UL, 0xa44ffabeUL 91*ebf0f73fSJohnny Huang }; 92*ebf0f73fSJohnny Huang 93*ebf0f73fSJohnny Huang static const u32 sha512_iv[16] = { 94*ebf0f73fSJohnny Huang 0x67e6096aUL, 0x08c9bcf3UL, 0x85ae67bbUL, 0x3ba7ca84UL, 95*ebf0f73fSJohnny Huang 0x72f36e3cUL, 0x2bf894feUL, 0x3af54fa5UL, 0xf1361d5fUL, 96*ebf0f73fSJohnny Huang 0x7f520e51UL, 0xd182e6adUL, 0x8c68059bUL, 0x1f6c3e2bUL, 97*ebf0f73fSJohnny Huang 0xabd9831fUL, 0x6bbd41fbUL, 0x19cde05bUL, 0x79217e13UL 98*ebf0f73fSJohnny Huang }; 99*ebf0f73fSJohnny Huang 100e31caa5aSChia-Wei Wang static phys_addr_t base; 101e31caa5aSChia-Wei Wang 102e31caa5aSChia-Wei Wang static int aspeed_hace_wait_completion(u32 reg, u32 flag, int timeout_us) 103e31caa5aSChia-Wei Wang { 104e31caa5aSChia-Wei Wang u32 val; 105e31caa5aSChia-Wei Wang 106e31caa5aSChia-Wei Wang return readl_poll_timeout(reg, val, (val & flag) == flag, timeout_us); 107e31caa5aSChia-Wei Wang } 108e31caa5aSChia-Wei Wang 109*ebf0f73fSJohnny Huang static void aspeed_ahash_fill_padding(struct aspeed_hash_ctx *ctx, unsigned int remainder) 110e31caa5aSChia-Wei Wang { 111*ebf0f73fSJohnny Huang unsigned int index, padlen; 112*ebf0f73fSJohnny Huang u64 bits[2]; 1130fdcca14SJoel Stanley 114*ebf0f73fSJohnny Huang if (ctx->block_size == 64) { 115*ebf0f73fSJohnny Huang bits[0] = cpu_to_be64(ctx->digcnt[0] << 3); 116*ebf0f73fSJohnny Huang index = (ctx->bufcnt + remainder) & 0x3f; 117*ebf0f73fSJohnny Huang padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); 118*ebf0f73fSJohnny Huang *(ctx->buffer + ctx->bufcnt) = 0x80; 119*ebf0f73fSJohnny Huang memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1); 120*ebf0f73fSJohnny Huang memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 8); 121*ebf0f73fSJohnny Huang ctx->bufcnt += padlen + 8; 122*ebf0f73fSJohnny Huang } else { 123*ebf0f73fSJohnny Huang bits[1] = cpu_to_be64(ctx->digcnt[0] << 3); 124*ebf0f73fSJohnny Huang bits[0] = cpu_to_be64(ctx->digcnt[1] << 3 | ctx->digcnt[0] >> 61); 125*ebf0f73fSJohnny Huang index = (ctx->bufcnt + remainder) & 0x7f; 126*ebf0f73fSJohnny Huang padlen = (index < 112) ? (112 - index) : ((128 + 112) - index); 127*ebf0f73fSJohnny Huang *(ctx->buffer + ctx->bufcnt) = 0x80; 128*ebf0f73fSJohnny Huang memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1); 129*ebf0f73fSJohnny Huang memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16); 130*ebf0f73fSJohnny Huang ctx->bufcnt += padlen + 16; 131*ebf0f73fSJohnny Huang } 132e31caa5aSChia-Wei Wang } 133e31caa5aSChia-Wei Wang 134*ebf0f73fSJohnny Huang static int hash_trigger(struct aspeed_hash_ctx *ctx, int hash_len) 135*ebf0f73fSJohnny Huang { 136e31caa5aSChia-Wei Wang if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) { 137e31caa5aSChia-Wei Wang debug("HACE error: engine busy\n"); 138e31caa5aSChia-Wei Wang return -EBUSY; 139e31caa5aSChia-Wei Wang } 140e31caa5aSChia-Wei Wang /* Clear pending completion status */ 141e31caa5aSChia-Wei Wang writel(HACE_HASH_ISR, base + ASPEED_HACE_STS); 142e31caa5aSChia-Wei Wang 143*ebf0f73fSJohnny Huang writel((u32)ctx->sg, base + ASPEED_HACE_HASH_SRC); 144*ebf0f73fSJohnny Huang writel((u32)ctx->digest, base + ASPEED_HACE_HASH_DIGEST_BUFF); 145*ebf0f73fSJohnny Huang writel((u32)ctx->digest, base + ASPEED_HACE_HASH_KEY_BUFF); 146*ebf0f73fSJohnny Huang writel(hash_len, base + ASPEED_HACE_HASH_DATA_LEN); 147*ebf0f73fSJohnny Huang writel(ctx->method, base + ASPEED_HACE_HASH_CMD); 148e31caa5aSChia-Wei Wang 149e31caa5aSChia-Wei Wang /* SHA512 hashing appears to have a througput of about 12MB/s */ 150*ebf0f73fSJohnny Huang return aspeed_hace_wait_completion(base + ASPEED_HACE_STS, 151e31caa5aSChia-Wei Wang HACE_HASH_ISR, 152*ebf0f73fSJohnny Huang 1000 + (hash_len >> 3)); 153e31caa5aSChia-Wei Wang } 154e31caa5aSChia-Wei Wang 155e31caa5aSChia-Wei Wang #if IS_ENABLED(CONFIG_SHA_PROG_HW_ACCEL) 156e31caa5aSChia-Wei Wang int hw_sha_init(struct hash_algo *algo, void **ctxp) 157e31caa5aSChia-Wei Wang { 158e31caa5aSChia-Wei Wang struct aspeed_hash_ctx *ctx; 159e31caa5aSChia-Wei Wang u32 method; 160*ebf0f73fSJohnny Huang u32 block_size; 161e31caa5aSChia-Wei Wang 162*ebf0f73fSJohnny Huang ctx = memalign(8, sizeof(struct aspeed_hash_ctx)); 163*ebf0f73fSJohnny Huang memset(ctx, '\0', sizeof(struct aspeed_hash_ctx)); 164*ebf0f73fSJohnny Huang 165*ebf0f73fSJohnny Huang method = HASH_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN; 166*ebf0f73fSJohnny Huang if (!strcmp(algo->name, "sha1")) { 167*ebf0f73fSJohnny Huang method |= HACE_ALGO_SHA1; 168*ebf0f73fSJohnny Huang block_size = 64; 169*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha1_iv, 32); 170*ebf0f73fSJohnny Huang } else if (!strcmp(algo->name, "sha256")) { 171*ebf0f73fSJohnny Huang method |= HACE_ALGO_SHA256; 172*ebf0f73fSJohnny Huang block_size = 64; 173*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha256_iv, 32); 174*ebf0f73fSJohnny Huang } else if (!strcmp(algo->name, "sha384")) { 175*ebf0f73fSJohnny Huang method |= HACE_ALGO_SHA384; 176*ebf0f73fSJohnny Huang block_size = 128; 177*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha384_iv, 64); 178*ebf0f73fSJohnny Huang } else if (!strcmp(algo->name, "sha512")) { 179*ebf0f73fSJohnny Huang method |= HACE_ALGO_SHA512; 180*ebf0f73fSJohnny Huang block_size = 128; 181*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha512_iv, 64); 182*ebf0f73fSJohnny Huang } else { 183e31caa5aSChia-Wei Wang return -ENOTSUPP; 184*ebf0f73fSJohnny Huang } 185e31caa5aSChia-Wei Wang 186e31caa5aSChia-Wei Wang if (!ctx) { 187e31caa5aSChia-Wei Wang debug("HACE error: Cannot allocate memory for context\n"); 188e31caa5aSChia-Wei Wang return -ENOMEM; 189e31caa5aSChia-Wei Wang } 190e31caa5aSChia-Wei Wang 191*ebf0f73fSJohnny Huang ctx->method = method; 192*ebf0f73fSJohnny Huang ctx->block_size = block_size; 193e31caa5aSChia-Wei Wang ctx->digest_size = algo->digest_size; 194*ebf0f73fSJohnny Huang ctx->bufcnt = 0; 195*ebf0f73fSJohnny Huang ctx->digcnt[0] = 0; 196*ebf0f73fSJohnny Huang ctx->digcnt[1] = 0; 197e31caa5aSChia-Wei Wang *ctxp = ctx; 198e31caa5aSChia-Wei Wang 199e31caa5aSChia-Wei Wang return 0; 200e31caa5aSChia-Wei Wang } 201e31caa5aSChia-Wei Wang 202e31caa5aSChia-Wei Wang int hw_sha_update(struct hash_algo *algo, void *hash_ctx, const void *buf, 203e31caa5aSChia-Wei Wang unsigned int size, int is_last) 204e31caa5aSChia-Wei Wang { 205e31caa5aSChia-Wei Wang struct aspeed_hash_ctx *ctx = hash_ctx; 206*ebf0f73fSJohnny Huang struct aspeed_sg *sg = ctx->sg; 207*ebf0f73fSJohnny Huang int rc; 208*ebf0f73fSJohnny Huang int remainder; 209*ebf0f73fSJohnny Huang int total_len; 210*ebf0f73fSJohnny Huang int i; 211e31caa5aSChia-Wei Wang 212*ebf0f73fSJohnny Huang ctx->digcnt[0] += size; 213*ebf0f73fSJohnny Huang if (ctx->digcnt[0] < size) 214*ebf0f73fSJohnny Huang ctx->digcnt[1]++; 215*ebf0f73fSJohnny Huang 216*ebf0f73fSJohnny Huang if (ctx->bufcnt + size < ctx->block_size) { 217*ebf0f73fSJohnny Huang memcpy(ctx->buffer + ctx->bufcnt, buf, size); 218*ebf0f73fSJohnny Huang ctx->bufcnt += size; 219*ebf0f73fSJohnny Huang return 0; 220*ebf0f73fSJohnny Huang } 221*ebf0f73fSJohnny Huang remainder = (size + ctx->bufcnt) % ctx->block_size; 222*ebf0f73fSJohnny Huang total_len = size + ctx->bufcnt - remainder; 223*ebf0f73fSJohnny Huang i = 0; 224*ebf0f73fSJohnny Huang if (ctx->bufcnt != 0) { 225*ebf0f73fSJohnny Huang sg[0].addr = (u32)ctx->buffer; 226*ebf0f73fSJohnny Huang sg[0].len = ctx->bufcnt; 227*ebf0f73fSJohnny Huang if (total_len == ctx->bufcnt) 228*ebf0f73fSJohnny Huang sg[0].len |= HACE_SG_LAST; 229*ebf0f73fSJohnny Huang i++; 230e31caa5aSChia-Wei Wang } 231e31caa5aSChia-Wei Wang 232*ebf0f73fSJohnny Huang if (total_len != ctx->bufcnt) { 233*ebf0f73fSJohnny Huang sg[i].addr = (u32)buf; 234*ebf0f73fSJohnny Huang sg[i].len = (total_len - ctx->bufcnt) | HACE_SG_LAST; 235*ebf0f73fSJohnny Huang } 236e31caa5aSChia-Wei Wang 237*ebf0f73fSJohnny Huang rc = hash_trigger(ctx, total_len); 238*ebf0f73fSJohnny Huang if (remainder != 0) { 239*ebf0f73fSJohnny Huang memcpy(ctx->buffer, buf + (total_len - ctx->bufcnt), remainder); 240*ebf0f73fSJohnny Huang ctx->bufcnt = remainder; 241*ebf0f73fSJohnny Huang } 242e31caa5aSChia-Wei Wang 243*ebf0f73fSJohnny Huang return rc; 244e31caa5aSChia-Wei Wang } 245e31caa5aSChia-Wei Wang 246e31caa5aSChia-Wei Wang int hw_sha_finish(struct hash_algo *algo, void *hash_ctx, void *dest_buf, int size) 247e31caa5aSChia-Wei Wang { 248e31caa5aSChia-Wei Wang struct aspeed_hash_ctx *ctx = hash_ctx; 249*ebf0f73fSJohnny Huang struct aspeed_sg *sg = ctx->sg; 250e31caa5aSChia-Wei Wang int rc; 251e31caa5aSChia-Wei Wang 252e31caa5aSChia-Wei Wang if (size < ctx->digest_size) { 253e31caa5aSChia-Wei Wang debug("HACE error: insufficient size on destination buffer\n"); 254e31caa5aSChia-Wei Wang free(ctx); 255e31caa5aSChia-Wei Wang return -EINVAL; 256e31caa5aSChia-Wei Wang } 257*ebf0f73fSJohnny Huang aspeed_ahash_fill_padding(ctx, 0); 258e31caa5aSChia-Wei Wang 259*ebf0f73fSJohnny Huang sg[0].addr = (u32)ctx->buffer; 260*ebf0f73fSJohnny Huang sg[0].len = ctx->bufcnt | HACE_SG_LAST; 261*ebf0f73fSJohnny Huang 262*ebf0f73fSJohnny Huang rc = hash_trigger(ctx, ctx->bufcnt); 263*ebf0f73fSJohnny Huang memcpy(dest_buf, ctx->digest, ctx->digest_size); 264e31caa5aSChia-Wei Wang 265e31caa5aSChia-Wei Wang free(ctx); 266e31caa5aSChia-Wei Wang 267e31caa5aSChia-Wei Wang return rc; 268e31caa5aSChia-Wei Wang } 269e31caa5aSChia-Wei Wang #endif 270e31caa5aSChia-Wei Wang 271*ebf0f73fSJohnny Huang static int sha_digest(const void *src, unsigned int length, void *digest, 272*ebf0f73fSJohnny Huang u32 sha_type) 273*ebf0f73fSJohnny Huang { 274*ebf0f73fSJohnny Huang struct aspeed_hash_ctx *ctx; 275*ebf0f73fSJohnny Huang int ret; 276*ebf0f73fSJohnny Huang 277*ebf0f73fSJohnny Huang if (!((u32)src & BIT(31))) { 278*ebf0f73fSJohnny Huang debug("HACE src out of bounds: can only copy from SDRAM\n"); 279*ebf0f73fSJohnny Huang return -EINVAL; 280*ebf0f73fSJohnny Huang } 281*ebf0f73fSJohnny Huang 282*ebf0f73fSJohnny Huang if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) { 283*ebf0f73fSJohnny Huang debug("HACE error: engine busy\n"); 284*ebf0f73fSJohnny Huang return -EBUSY; 285*ebf0f73fSJohnny Huang } 286*ebf0f73fSJohnny Huang 287*ebf0f73fSJohnny Huang ctx = memalign(8, sizeof(struct aspeed_hash_ctx)); 288*ebf0f73fSJohnny Huang memset(ctx, '\0', sizeof(struct aspeed_hash_ctx)); 289*ebf0f73fSJohnny Huang 290*ebf0f73fSJohnny Huang if (!ctx) { 291*ebf0f73fSJohnny Huang debug("HACE error: Cannot allocate memory for context\n"); 292*ebf0f73fSJohnny Huang return -ENOMEM; 293*ebf0f73fSJohnny Huang } 294*ebf0f73fSJohnny Huang ctx->method = HASH_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN; 295*ebf0f73fSJohnny Huang 296*ebf0f73fSJohnny Huang switch (sha_type) { 297*ebf0f73fSJohnny Huang case ASPEED_SHA_TYPE_SHA1: 298*ebf0f73fSJohnny Huang ctx->block_size = 64; 299*ebf0f73fSJohnny Huang ctx->digest_size = 20; 300*ebf0f73fSJohnny Huang ctx->method |= HACE_ALGO_SHA1; 301*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha1_iv, 32); 302*ebf0f73fSJohnny Huang break; 303*ebf0f73fSJohnny Huang case ASPEED_SHA_TYPE_SHA256: 304*ebf0f73fSJohnny Huang ctx->block_size = 64; 305*ebf0f73fSJohnny Huang ctx->digest_size = 32; 306*ebf0f73fSJohnny Huang ctx->method |= HACE_ALGO_SHA256; 307*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha256_iv, 32); 308*ebf0f73fSJohnny Huang break; 309*ebf0f73fSJohnny Huang case ASPEED_SHA_TYPE_SHA384: 310*ebf0f73fSJohnny Huang ctx->block_size = 128; 311*ebf0f73fSJohnny Huang ctx->digest_size = 64; 312*ebf0f73fSJohnny Huang ctx->method |= HACE_ALGO_SHA384; 313*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha384_iv, 64); 314*ebf0f73fSJohnny Huang break; 315*ebf0f73fSJohnny Huang case ASPEED_SHA_TYPE_SHA512: 316*ebf0f73fSJohnny Huang ctx->block_size = 128; 317*ebf0f73fSJohnny Huang ctx->digest_size = 64; 318*ebf0f73fSJohnny Huang ctx->method |= HACE_ALGO_SHA512; 319*ebf0f73fSJohnny Huang memcpy(ctx->digest, sha512_iv, 64); 320*ebf0f73fSJohnny Huang break; 321*ebf0f73fSJohnny Huang default: 322*ebf0f73fSJohnny Huang return -ENOTSUPP; 323*ebf0f73fSJohnny Huang } 324*ebf0f73fSJohnny Huang 325*ebf0f73fSJohnny Huang ctx->digcnt[0] = length; 326*ebf0f73fSJohnny Huang ctx->digcnt[1] = 0; 327*ebf0f73fSJohnny Huang 328*ebf0f73fSJohnny Huang aspeed_ahash_fill_padding(ctx, length); 329*ebf0f73fSJohnny Huang 330*ebf0f73fSJohnny Huang if (length != 0) { 331*ebf0f73fSJohnny Huang ctx->sg[0].addr = (u32)src; 332*ebf0f73fSJohnny Huang ctx->sg[0].len = length; 333*ebf0f73fSJohnny Huang ctx->sg[1].addr = (u32)ctx->buffer; 334*ebf0f73fSJohnny Huang ctx->sg[1].len = ctx->bufcnt | HACE_SG_LAST; 335*ebf0f73fSJohnny Huang } else { 336*ebf0f73fSJohnny Huang ctx->sg[0].addr = (u32)ctx->buffer; 337*ebf0f73fSJohnny Huang ctx->sg[0].len = ctx->bufcnt | HACE_SG_LAST; 338*ebf0f73fSJohnny Huang } 339*ebf0f73fSJohnny Huang 340*ebf0f73fSJohnny Huang ret = hash_trigger(ctx, length + ctx->bufcnt); 341*ebf0f73fSJohnny Huang memcpy(digest, ctx->digest, ctx->digest_size); 342*ebf0f73fSJohnny Huang free(ctx); 343*ebf0f73fSJohnny Huang 344*ebf0f73fSJohnny Huang return ret; 345*ebf0f73fSJohnny Huang } 346*ebf0f73fSJohnny Huang 347*ebf0f73fSJohnny Huang void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, 348*ebf0f73fSJohnny Huang unsigned char *pout, unsigned int chunk_size) 349*ebf0f73fSJohnny Huang { 350*ebf0f73fSJohnny Huang int rc; 351*ebf0f73fSJohnny Huang 352*ebf0f73fSJohnny Huang rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA1); 353*ebf0f73fSJohnny Huang if (rc) 354*ebf0f73fSJohnny Huang debug("HACE failure: %d\n", rc); 355*ebf0f73fSJohnny Huang } 356*ebf0f73fSJohnny Huang 357*ebf0f73fSJohnny Huang void hw_sha256(const unsigned char *pbuf, unsigned int buf_len, 358*ebf0f73fSJohnny Huang unsigned char *pout, unsigned int chunk_size) 359*ebf0f73fSJohnny Huang { 360*ebf0f73fSJohnny Huang int rc; 361*ebf0f73fSJohnny Huang 362*ebf0f73fSJohnny Huang rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA256); 363*ebf0f73fSJohnny Huang if (rc) 364*ebf0f73fSJohnny Huang debug("HACE failure: %d\n", rc); 365*ebf0f73fSJohnny Huang } 366*ebf0f73fSJohnny Huang 367*ebf0f73fSJohnny Huang void hw_sha384(const unsigned char *pbuf, unsigned int buf_len, 368*ebf0f73fSJohnny Huang unsigned char *pout, unsigned int chunk_size) 369*ebf0f73fSJohnny Huang { 370*ebf0f73fSJohnny Huang int rc; 371*ebf0f73fSJohnny Huang 372*ebf0f73fSJohnny Huang rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA384); 373*ebf0f73fSJohnny Huang if (rc) 374*ebf0f73fSJohnny Huang debug("HACE failure: %d\n", rc); 375*ebf0f73fSJohnny Huang } 376*ebf0f73fSJohnny Huang 377*ebf0f73fSJohnny Huang void hw_sha512(const unsigned char *pbuf, unsigned int buf_len, 378*ebf0f73fSJohnny Huang unsigned char *pout, unsigned int chunk_size) 379*ebf0f73fSJohnny Huang { 380*ebf0f73fSJohnny Huang int rc; 381*ebf0f73fSJohnny Huang 382*ebf0f73fSJohnny Huang rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA512); 383*ebf0f73fSJohnny Huang if (rc) 384*ebf0f73fSJohnny Huang debug("HACE failure: %d\n", rc); 385*ebf0f73fSJohnny Huang } 386*ebf0f73fSJohnny Huang 387e31caa5aSChia-Wei Wang static int aspeed_hace_probe(struct udevice *dev) 388e31caa5aSChia-Wei Wang { 389e31caa5aSChia-Wei Wang struct aspeed_hace *hace = dev_get_priv(dev); 390e31caa5aSChia-Wei Wang int ret; 391e31caa5aSChia-Wei Wang 392e31caa5aSChia-Wei Wang ret = clk_get_by_index(dev, 0, &hace->clk); 393e31caa5aSChia-Wei Wang if (ret < 0) { 394e31caa5aSChia-Wei Wang debug("Can't get clock for %s: %d\n", dev->name, ret); 395e31caa5aSChia-Wei Wang return ret; 396e31caa5aSChia-Wei Wang } 397e31caa5aSChia-Wei Wang 398e31caa5aSChia-Wei Wang ret = clk_enable(&hace->clk); 399e31caa5aSChia-Wei Wang if (ret) { 400e31caa5aSChia-Wei Wang debug("Failed to enable fsi clock (%d)\n", ret); 401e31caa5aSChia-Wei Wang return ret; 402e31caa5aSChia-Wei Wang } 403e31caa5aSChia-Wei Wang 404e31caa5aSChia-Wei Wang /* As the crypto code does not pass us any driver state */ 405e31caa5aSChia-Wei Wang base = devfdt_get_addr(dev); 406e31caa5aSChia-Wei Wang 407e31caa5aSChia-Wei Wang return ret; 408e31caa5aSChia-Wei Wang } 409e31caa5aSChia-Wei Wang 410e31caa5aSChia-Wei Wang static int aspeed_hace_remove(struct udevice *dev) 411e31caa5aSChia-Wei Wang { 412e31caa5aSChia-Wei Wang struct aspeed_hace *hace = dev_get_priv(dev); 413e31caa5aSChia-Wei Wang 414e31caa5aSChia-Wei Wang clk_disable(&hace->clk); 415e31caa5aSChia-Wei Wang 416e31caa5aSChia-Wei Wang return 0; 417e31caa5aSChia-Wei Wang } 418e31caa5aSChia-Wei Wang 419e31caa5aSChia-Wei Wang static const struct udevice_id aspeed_hace_ids[] = { 420e31caa5aSChia-Wei Wang { .compatible = "aspeed,ast2600-hace" }, 421e31caa5aSChia-Wei Wang { } 422e31caa5aSChia-Wei Wang }; 423e31caa5aSChia-Wei Wang 424e31caa5aSChia-Wei Wang U_BOOT_DRIVER(aspeed_hace) = { 425e31caa5aSChia-Wei Wang .name = "aspeed_hace", 426e31caa5aSChia-Wei Wang .id = UCLASS_MISC, 427e31caa5aSChia-Wei Wang .of_match = aspeed_hace_ids, 428e31caa5aSChia-Wei Wang .probe = aspeed_hace_probe, 429e31caa5aSChia-Wei Wang .remove = aspeed_hace_remove, 430e31caa5aSChia-Wei Wang .priv_auto_alloc_size = sizeof(struct aspeed_hace), 431e31caa5aSChia-Wei Wang .flags = DM_FLAG_PRE_RELOC, 432e31caa5aSChia-Wei Wang }; 433