/* * Driver for EIP97 cryptographic accelerator. * * Copyright (c) 2018 AVM GmbH * * SPDX-License-Identifier: GPL-2.0-only * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This driver is heavily based on the Mediatek driver from Ryder Lee. * */ #ifndef __EIP97_PLATFORM_H_ #define __EIP97_PLATFORM_H_ #include #include #include #include "eip97-regs.h" /* Transform state control word 0 fields */ #define EIP97_TFM_SHA1 (0x2 << 23) #define EIP97_TFM_SHA224 (0x4 << 23) #define EIP97_TFM_SHA512 (0x5 << 23) #define EIP97_TFM_AES_AEAD_DIGEST (0x2 << 21) #define EIP97_TFM_AES_128BITS (0xa << 16) #define EIP97_TFM_AES_192BITS (0xc << 16) #define EIP97_TFM_AES_256BITS (0xe << 16) #define EIP97_TFM_CONTAINS_KEY (0x1 << 16) #define EIP97_TFM_SIZE(x) ((x) << 8) #define EIP97_TFM_HASH_OUT (0x2 << 0) #define EIP97_TFM_BASIC_OUT (0x4 << 0) #define EIP97_TFM_BASIC_IN (0x5 << 0) #define EIP97_TFM_CRYPT_THEN_HASH_OUT (0x6 << 0) #define EIP97_TFM_CRYPT_THEN_HASH_IN (0x7 << 0) #define EIP97_TFM_HASH_THEN_CRYPT_OUT (0xe << 0) #define EIP97_TFM_HASH_THEN_CRYPT_IN (0xf << 0) #define EIP97_TFM_ECB (0x0 << 0) #define EIP97_TFM_CBC (0x1 << 0) /* Transform state control word 1 fields */ #define EIP97_TFM_STORE_HASH_RESULT BIT(19) #define EIP97_TFM_ENCRYPT_HASH_RESULT BIT(17) #define EIP97_TFM_COUNTER_MODE_IV (0x1 << 10) #define EIP97_TFM_IV3 BIT(8) #define EIP97_TFM_IV2 BIT(7) #define EIP97_TFM_IV1 BIT(6) #define EIP97_TFM_IV0 BIT(5) #define EIP97_TFM_CRYPT_MODE_UNDEFINED (0x2 << 0) #define EIP97_TFM_CTR_LOAD (0x6 << 0) #define SIZE_IN_WORDS(x) DIV_ROUND_UP((x), 4) #define SIZE_IN_BYTES(x) ((x) << 2) enum eip97_ring_id { EIP97_RING0, EIP97_RING1, EIP97_RING2, EIP97_RING3, EIP97_RING_MAX }; #define EIP97_IRQ_NUM 5 #define EIP97_IRQ_RDR0 BIT(1) #define EIP97_IRQ_RDR1 BIT(3) #define EIP97_IRQ_RDR2 BIT(5) #define EIP97_IRQ_RDR3 BIT(7) #define EIP97_IRQ_RDR(x) BIT(1 + 2*(x)) #define EIP97_DESC_LAST BIT(22) #define EIP97_DESC_FIRST BIT(23) #define EIP97_DESC_BUF_LEN(x) (x) #define EIP97_DESC_TAG(x) ((x) & GENMASK(23, 0)) #define EIP97_CT_USE_EIP97_MODE 0x00020000 /** * struct eip97_cd - Crypto operation command descriptor * @hdr: descriptor control header * @buf: DMA address of input buffer segment * @ct: DMA address of command token that controls operation flow * @ct_hdr: command token control header * @tag: user-defined field * @tfm: DMA address of transform state * @bound: align descriptors offset boundary * * Structure passed to the crypto engine to describe where input data * needs to be fetched and how it needs to be processed. */ struct eip97_cd { u32 hdr; u32 inbuf; u32 ct; u32 ct_hdr; u32 tag; u32 tfm; u32 bound[2]; }; #define EIP97_CD_OFF SIZE_IN_WORDS(sizeof(struct eip97_cd)) #define EIP97_CD_SZ (EIP97_CD_OFF - 2) #define EIP97_CD_CNT(x) SIZE_IN_BYTES(EIP97_CD_OFF * (x)) #define EIP97_CD_CT_LEN(x) ((x) << 24) /** * struct eip97_rd - Crypto operation result descriptor * @hdr: descriptor control header * @buf: DMA address of output buffer segment * @res1: result information * @res2: result information * @tag: user-defined field * @res3: result information * @bound: align descriptors offset boundary * * Structure passed to the crypto engine to describe where output data * needs to be pushed to. Also holds additional information on errors or * success after the crypto operation finishes. */ struct eip97_rd { u32 hdr; u32 outbuf; u32 res1; u32 res2; u32 tag; u32 res3; u32 bound[2]; }; #define EIP97_RD_OFF SIZE_IN_WORDS(sizeof(struct eip97_rd)) #define EIP97_RD_SZ (EIP97_RD_OFF - 2) #define EIP97_RD_CNT(x) SIZE_IN_BYTES(EIP97_RD_OFF * (x)) #define EIP97_RD_RESULT_SIZE(x) ((x) & GENMASK(16, 0)) #define EIP97_RD_ERR(x) (((x) >> 17) & GENMASK(14, 0)) #define EIP97_RD_BUF_OVF BIT(21) #define EIP97_RD_DESC_OVF BIT(20) typedef u32 eip97_err_t; #define EIP97_SUCCESS 0 #define EIP97_ERR_PACKET_LENGTH BIT(0) #define EIP97_ERR_UNKNOWN_INSTR BIT(1) #define EIP97_ERR_TOO_MANY_BYPASS_DATA BIT(2) #define EIP97_ERR_CRYPTO_BLOCKSIZE BIT(3) #define EIP97_ERR_HASH_BLOCKSIZE BIT(4) #define EIP97_ERR_INVALID_MODE_COMBINATION BIT(5) #define EIP97_ERR_INVALID_ALGORITHM BIT(6) #define EIP97_ERR_HASH_INPUT_OVERFLOW BIT(7) #define EIP97_ERR_TTL_HOP_UNDERFLOW BIT(8) #define EIP97_ERR_AUTHENTICATION BIT(9) #define EIP97_ERR_SN_CHECK BIT(10) #define EIP97_ERR_SPI_CHECK BIT(11) #define EIP97_ERR_WRONG_CHECKSUM BIT(12) #define EIP97_ERR_PAD_VERIFICATION BIT(13) #define EIP97_ERR_TIMEOUT BIT(14) #define EIP97_ERR_BUFFER_OVERFLOW BIT(15) #define EIP97_ERR_DESCRIPTOR_OVERFLOW BIT(16) #define EIP97_ERR_CHECK_FAIL ( EIP97_ERR_TTL_HOP_UNDERFLOW \ | EIP97_ERR_AUTHENTICATION \ | EIP97_ERR_SN_CHECK \ | EIP97_ERR_SPI_CHECK \ | EIP97_ERR_WRONG_CHECKSUM \ | EIP97_ERR_PAD_VERIFICATION ) struct eip97_cryp; /** * struct eip97_ring - Ring of command and result descriptors * * @cmd_base: pointer to CD ring base * @cmd_dma: DMA address of CD ring * @cmd_prep: pointer to next CD to be prepared for a request * @cmd_proc: pointer to next CD to be processed after a request * @cmd_num: total number of descriptors in CD ring * * @res_base: pointer to RD ring base * @res_dma: DMA address of RD ring * @res_prep: pointer to next RD to be prepared for a request * @res_proc: pointer to next RD to be processed after a request * @res_num: total number of descriptors in RD ring * * Describes a descriptor ring that exchanges crypto operation requests * and results with the crypto hardware. It consists of two parts, the * command descriptors (CDs) and the result descriptors (RDs). * CDs describe the input and RDs the output of a crypto operation. */ struct eip97_ring { enum eip97_ring_id ring_id; struct eip97_cryp *cryp; volatile struct eip97_cd *cmd_base; dma_addr_t cmd_dma; volatile struct eip97_cd * volatile cmd_prep; volatile struct eip97_cd * volatile cmd_proc; u32 cmd_num; volatile struct eip97_rd *res_base; dma_addr_t res_dma; volatile struct eip97_rd * volatile res_prep; volatile struct eip97_rd * volatile res_proc; u32 res_num; }; enum eip97_op_type { EIP97_INVALID_OP_TYPE = 0, EIP97_SKCIPHER, EIP97_AEAD, EIP97_AHASH }; enum crypt_direction { EIP97_ENCRYPT, EIP97_DECRYPT }; struct eip97_debug { atomic_t unaligned_ops; atomic_t total_ops; atomic_t ring_full; atomic_t ring_empty; atomic_t err_ops; atomic_t tx_ops; atomic_t rx_ops; atomic_t tests_total; atomic_t tests_success; atomic_t tests_fail; struct dentry *dir; }; /** * struct eip97_cryp - Cryptographic device * @base: pointer to mapped register I/O base * @irq: global system and rings IRQ * @dev: pointer to device * @clk_cryp: pointer to crypto clock * @ring: array of ring descriptions * @irq_bh: tasklet for IRQ postprocessing * @worker: workqueue for IRQ postpostprocessing * @tags: tag lookup table for requests on ring 0, * with at least one tag per possible request * @tags_num: Number of tag lookup table entries * @taglock: spinlock to protect @tags * @dev_list: list of EIP97 devices * @debug: debug statistics * * Structure storing cryptographic device information. */ struct eip97_cryp { void __iomem *base; int irq[EIP97_IRQ_NUM]; struct device *dev; struct clk *clk_cryp; struct eip97_ring *ring[EIP97_RING_MAX]; struct tasklet_struct irq_bh[EIP97_RING_MAX]; enum eip97_op_type **tags; u32 tags_num; spinlock_t taglock; struct list_head dev_list; struct eip97_debug debug; }; struct eip97_cryp *eip97_find_dev(void); int eip97_alloc_tag(struct eip97_cryp *cryp, enum eip97_op_type *op_type); static inline void eip97_write_state_le(__le32 *dst, const u32 *src, u32 words) { int i; for (i = 0; i < words; i++) dst[i] = cpu_to_le32(src[i]); } static inline void eip97_write_state_be(__be32 *dst, const u32 *src, u32 words) { int i; for (i = 0; i < words; i++) dst[i] = cpu_to_be32(src[i]); } static inline void eip97_read_state_le(u32 *dst, const __le32 *src, u32 words) { int i; for (i = 0; i < words; i++) dst[i] = le32_to_cpu(src[i]); } /* * eip97_create_cmd_descs - Create command descriptors from scatterlist * @sg - The scatterlist to create command descriptors from * @sg_bytes - The number of bytes of data from the scatterlist that should * command descriptors be created for * @ring - Ring the command descriptors should be created in * @ct - Pointer to the command token * @ct_flags - Additional command token header flags to be set * @ct_len - Length of the command token * @tag - Identifier for the described operation (only 3 lower bytes) * @tfm - Pointer to the transform state * * Create a number of command descriptors to describe a number of bytes from a * scatterlist for a request in the given ring. * The new command descriptors will be flagged accordingly as first and * last one of the given scatterlist, and the first one will also include the * necessary control data like @ct, @ct_len, @tag, and @tfm. * * IMPORTANT: This function operates directly on the ring, so you need to * already hold ring->lock. * * This function returns the number of command descriptors created, or a * negative errno code on fail. */ int eip97_create_cmd_descs(struct scatterlist *sg, u32 sg_bytes, struct eip97_ring *ring, dma_addr_t ct, u32 ct_flags, u32 ct_len, u32 tag, dma_addr_t tfm); /* * eip97_create_res_descs - Create result descriptors from scatterlist * @sg - The scatterlist to create command descriptors from * @sg_bytes - The number of bytes of data from the scatterlist that should * command descriptors be created for * @ring - Ring the command descriptors should be created in * @tag - Identifier for the described operation (only 3 lower bytes) * * Create a number of result descriptors to describe a number of bytes from a * scatterlist for a request in the given ring. * The new result descriptors will be flagged accordingly as first and * last one of the given scatterlist, and the first one will also include the * necessary control data like @tag etc. * * IMPORTANT: This function operates directly on the ring, so you need to * already hold ring->lock. * * This function returns the number of result descriptors created, or a * negative errno code on fail. */ int eip97_create_res_descs(struct scatterlist *sg, u32 sg_bytes, struct eip97_ring *ring, u32 tag); static inline int cd_ring_empty(struct eip97_ring *ring) { return ring->cmd_proc == ring->cmd_prep; } static inline int rd_ring_empty(struct eip97_ring *ring) { return ring->res_proc == ring->res_prep; } #endif /* __EIP97_PLATFORM_H_ */