root/drivers/crypto/aspeed/aspeed-hace.h
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __ASPEED_HACE_H__
#define __ASPEED_HACE_H__

#include <crypto/aes.h>
#include <crypto/engine.h>
#include <crypto/hash.h>
#include <crypto/sha2.h>
#include <linux/bits.h>
#include <linux/compiler_attributes.h>
#include <linux/interrupt.h>
#include <linux/types.h>

/*****************************
 *                           *
 * HACE register definitions *
 *                           *
 * ***************************/
#define ASPEED_HACE_SRC                 0x00    /* Crypto Data Source Base Address Register */
#define ASPEED_HACE_DEST                0x04    /* Crypto Data Destination Base Address Register */
#define ASPEED_HACE_CONTEXT             0x08    /* Crypto Context Buffer Base Address Register */
#define ASPEED_HACE_DATA_LEN            0x0C    /* Crypto Data Length Register */
#define ASPEED_HACE_CMD                 0x10    /* Crypto Engine Command Register */

/* G5 */
#define ASPEED_HACE_TAG                 0x18    /* HACE Tag Register */
/* G6 */
#define ASPEED_HACE_GCM_ADD_LEN         0x14    /* Crypto AES-GCM Additional Data Length Register */
#define ASPEED_HACE_GCM_TAG_BASE_ADDR   0x18    /* Crypto AES-GCM Tag Write Buff Base Address Reg */

#define ASPEED_HACE_STS                 0x1C    /* HACE Status Register */

#define ASPEED_HACE_HASH_SRC            0x20    /* Hash Data Source Base Address Register */
#define ASPEED_HACE_HASH_DIGEST_BUFF    0x24    /* Hash Digest Write Buffer Base Address Register */
#define ASPEED_HACE_HASH_KEY_BUFF       0x28    /* Hash HMAC Key Buffer Base Address Register */
#define ASPEED_HACE_HASH_DATA_LEN       0x2C    /* Hash Data Length Register */
#define ASPEED_HACE_HASH_CMD            0x30    /* Hash Engine Command Register */

/* crypto cmd */
#define  HACE_CMD_SINGLE_DES            0
#define  HACE_CMD_TRIPLE_DES            BIT(17)
#define  HACE_CMD_AES_SELECT            0
#define  HACE_CMD_DES_SELECT            BIT(16)
#define  HACE_CMD_ISR_EN                BIT(12)
#define  HACE_CMD_CONTEXT_SAVE_ENABLE   (0)
#define  HACE_CMD_CONTEXT_SAVE_DISABLE  BIT(9)
#define  HACE_CMD_AES                   (0)
#define  HACE_CMD_DES                   (0)
#define  HACE_CMD_RC4                   BIT(8)
#define  HACE_CMD_DECRYPT               (0)
#define  HACE_CMD_ENCRYPT               BIT(7)

#define  HACE_CMD_ECB                   (0x0 << 4)
#define  HACE_CMD_CBC                   (0x1 << 4)
#define  HACE_CMD_CFB                   (0x2 << 4)
#define  HACE_CMD_OFB                   (0x3 << 4)
#define  HACE_CMD_CTR                   (0x4 << 4)
#define  HACE_CMD_OP_MODE_MASK          (0x7 << 4)

#define  HACE_CMD_AES128                (0x0 << 2)
#define  HACE_CMD_AES192                (0x1 << 2)
#define  HACE_CMD_AES256                (0x2 << 2)
#define  HACE_CMD_OP_CASCADE            (0x3)
#define  HACE_CMD_OP_INDEPENDENT        (0x1)

/* G5 */
#define  HACE_CMD_RI_WO_DATA_ENABLE     (0)
#define  HACE_CMD_RI_WO_DATA_DISABLE    BIT(11)
#define  HACE_CMD_CONTEXT_LOAD_ENABLE   (0)
#define  HACE_CMD_CONTEXT_LOAD_DISABLE  BIT(10)
/* G6 */
#define  HACE_CMD_AES_KEY_FROM_OTP      BIT(24)
#define  HACE_CMD_GHASH_TAG_XOR_EN      BIT(23)
#define  HACE_CMD_GHASH_PAD_LEN_INV     BIT(22)
#define  HACE_CMD_GCM_TAG_ADDR_SEL      BIT(21)
#define  HACE_CMD_MBUS_REQ_SYNC_EN      BIT(20)
#define  HACE_CMD_DES_SG_CTRL           BIT(19)
#define  HACE_CMD_SRC_SG_CTRL           BIT(18)
#define  HACE_CMD_CTR_IV_AES_96         (0x1 << 14)
#define  HACE_CMD_CTR_IV_DES_32         (0x1 << 14)
#define  HACE_CMD_CTR_IV_AES_64         (0x2 << 14)
#define  HACE_CMD_CTR_IV_AES_32         (0x3 << 14)
#define  HACE_CMD_AES_KEY_HW_EXP        BIT(13)
#define  HACE_CMD_GCM                   (0x5 << 4)

/* interrupt status reg */
#define  HACE_CRYPTO_ISR                BIT(12)
#define  HACE_HASH_ISR                  BIT(9)
#define  HACE_HASH_BUSY                 BIT(0)

/* hash cmd reg */
#define  HASH_CMD_MBUS_REQ_SYNC_EN      BIT(20)
#define  HASH_CMD_HASH_SRC_SG_CTRL      BIT(18)
#define  HASH_CMD_SHA512_224            (0x3 << 10)
#define  HASH_CMD_SHA512_256            (0x2 << 10)
#define  HASH_CMD_SHA384                (0x1 << 10)
#define  HASH_CMD_SHA512                (0)
#define  HASH_CMD_INT_ENABLE            BIT(9)
#define  HASH_CMD_HMAC                  (0x1 << 7)
#define  HASH_CMD_ACC_MODE              (0x2 << 7)
#define  HASH_CMD_HMAC_KEY              (0x3 << 7)
#define  HASH_CMD_SHA1                  (0x2 << 4)
#define  HASH_CMD_SHA224                (0x4 << 4)
#define  HASH_CMD_SHA256                (0x5 << 4)
#define  HASH_CMD_SHA512_SER            (0x6 << 4)
#define  HASH_CMD_SHA_SWAP              (0x2 << 2)

#define HASH_SG_LAST_LIST               BIT(31)

#define CRYPTO_FLAGS_BUSY               BIT(1)

#define SHA_OP_UPDATE                   1
#define SHA_OP_FINAL                    2

#define SHA_FLAGS_SHA1                  BIT(0)
#define SHA_FLAGS_SHA224                BIT(1)
#define SHA_FLAGS_SHA256                BIT(2)
#define SHA_FLAGS_SHA384                BIT(3)
#define SHA_FLAGS_SHA512                BIT(4)
#define SHA_FLAGS_SHA512_224            BIT(5)
#define SHA_FLAGS_SHA512_256            BIT(6)
#define SHA_FLAGS_FINUP                 BIT(9)
#define SHA_FLAGS_MASK                  (0xff)

#define ASPEED_CRYPTO_SRC_DMA_BUF_LEN   0xa000
#define ASPEED_CRYPTO_DST_DMA_BUF_LEN   0xa000
#define ASPEED_CRYPTO_GCM_TAG_OFFSET    0x9ff0
#define ASPEED_HASH_SRC_DMA_BUF_LEN     0xa000
#define ASPEED_HASH_QUEUE_LENGTH        50

#define HACE_CMD_IV_REQUIRE             (HACE_CMD_CBC | HACE_CMD_CFB | \
                                         HACE_CMD_OFB | HACE_CMD_CTR)

struct aspeed_hace_dev;
struct scatterlist;

typedef int (*aspeed_hace_fn_t)(struct aspeed_hace_dev *);

struct aspeed_sg_list {
        __le32 len;
        __le32 phy_addr;
};

struct aspeed_engine_hash {
        struct tasklet_struct           done_task;
        unsigned long                   flags;
        struct ahash_request            *req;

        /* input buffer */
        void                            *ahash_src_addr;
        dma_addr_t                      ahash_src_dma_addr;

        dma_addr_t                      src_dma;
        dma_addr_t                      digest_dma;

        size_t                          src_length;

        /* callback func */
        aspeed_hace_fn_t                resume;
        aspeed_hace_fn_t                dma_prepare;
};

struct aspeed_sham_ctx {
        struct aspeed_hace_dev          *hace_dev;
};

struct aspeed_sham_reqctx {
        /* DMA buffer written by hardware */
        u8                      digest[SHA512_DIGEST_SIZE] __aligned(64);

        /* Software state sorted by size. */
        u64                     digcnt[2];

        unsigned long           flags;          /* final update flag should no use*/
        u32                     cmd;            /* trigger cmd */

        /* walk state */
        struct scatterlist      *src_sg;
        int                     src_nents;
        unsigned int            offset;         /* offset in current sg */
        unsigned int            total;          /* per update length */

        size_t                  digsize;
        size_t                  block_size;
        size_t                  ivsize;

        dma_addr_t              buffer_dma_addr;
        dma_addr_t              digest_dma_addr;

        /* This is DMA too but read-only for hardware. */
        u8                      buffer[SHA512_BLOCK_SIZE + 16];
};

struct aspeed_engine_crypto {
        struct tasklet_struct           done_task;
        unsigned long                   flags;
        struct skcipher_request         *req;

        /* context buffer */
        void                            *cipher_ctx;
        dma_addr_t                      cipher_ctx_dma;

        /* input buffer, could be single/scatter-gather lists */
        void                            *cipher_addr;
        dma_addr_t                      cipher_dma_addr;

        /* output buffer, only used in scatter-gather lists */
        void                            *dst_sg_addr;
        dma_addr_t                      dst_sg_dma_addr;

        /* callback func */
        aspeed_hace_fn_t                resume;
};

struct aspeed_cipher_ctx {
        struct aspeed_hace_dev          *hace_dev;
        int                             key_len;
        u8                              key[AES_MAX_KEYLENGTH];

        /* callback func */
        aspeed_hace_fn_t                start;

        struct crypto_skcipher          *fallback_tfm;
};

struct aspeed_cipher_reqctx {
        int enc_cmd;
        int src_nents;
        int dst_nents;

        struct skcipher_request         fallback_req;   /* keep at the end */
};

struct aspeed_hace_dev {
        void __iomem                    *regs;
        struct device                   *dev;
        int                             irq;
        struct clk                      *clk;
        unsigned long                   version;

        struct crypto_engine            *crypt_engine_hash;
        struct crypto_engine            *crypt_engine_crypto;

        struct aspeed_engine_hash       hash_engine;
        struct aspeed_engine_crypto     crypto_engine;
};

struct aspeed_hace_alg {
        struct aspeed_hace_dev          *hace_dev;

        const char                      *alg_base;

        union {
                struct skcipher_engine_alg skcipher;
                struct ahash_engine_alg ahash;
        } alg;
};

enum aspeed_version {
        AST2500_VERSION = 5,
        AST2600_VERSION
};

#define ast_hace_write(hace, val, offset)       \
        writel((val), (hace)->regs + (offset))
#define ast_hace_read(hace, offset)             \
        readl((hace)->regs + (offset))

void aspeed_register_hace_hash_algs(struct aspeed_hace_dev *hace_dev);
void aspeed_unregister_hace_hash_algs(struct aspeed_hace_dev *hace_dev);
void aspeed_register_hace_crypto_algs(struct aspeed_hace_dev *hace_dev);
void aspeed_unregister_hace_crypto_algs(struct aspeed_hace_dev *hace_dev);

#endif