162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AMD Cryptographic Coprocessor (CCP) driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2013,2017 Advanced Micro Devices, Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Tom Lendacky <thomas.lendacky@amd.com> 862306a36Sopenharmony_ci * Author: Gary R Hook <gary.hook@amd.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifndef __CCP_DEV_H__ 1262306a36Sopenharmony_ci#define __CCP_DEV_H__ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/device.h> 1562306a36Sopenharmony_ci#include <linux/spinlock.h> 1662306a36Sopenharmony_ci#include <linux/mutex.h> 1762306a36Sopenharmony_ci#include <linux/list.h> 1862306a36Sopenharmony_ci#include <linux/wait.h> 1962306a36Sopenharmony_ci#include <linux/dma-direction.h> 2062306a36Sopenharmony_ci#include <linux/dmapool.h> 2162306a36Sopenharmony_ci#include <linux/hw_random.h> 2262306a36Sopenharmony_ci#include <linux/bitops.h> 2362306a36Sopenharmony_ci#include <linux/interrupt.h> 2462306a36Sopenharmony_ci#include <linux/irqreturn.h> 2562306a36Sopenharmony_ci#include <linux/dmaengine.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include "sp-dev.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define MAX_CCP_NAME_LEN 16 3062306a36Sopenharmony_ci#define MAX_DMAPOOL_NAME_LEN 32 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define MAX_HW_QUEUES 5 3362306a36Sopenharmony_ci#define MAX_CMD_QLEN 100 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define TRNG_RETRIES 10 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define CACHE_NONE 0x00 3862306a36Sopenharmony_ci#define CACHE_WB_NO_ALLOC 0xb7 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/****** Register Mappings ******/ 4162306a36Sopenharmony_ci#define Q_MASK_REG 0x000 4262306a36Sopenharmony_ci#define TRNG_OUT_REG 0x00c 4362306a36Sopenharmony_ci#define IRQ_MASK_REG 0x040 4462306a36Sopenharmony_ci#define IRQ_STATUS_REG 0x200 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define DEL_CMD_Q_JOB 0x124 4762306a36Sopenharmony_ci#define DEL_Q_ACTIVE 0x00000200 4862306a36Sopenharmony_ci#define DEL_Q_ID_SHIFT 6 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define CMD_REQ0 0x180 5162306a36Sopenharmony_ci#define CMD_REQ_INCR 0x04 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#define CMD_Q_STATUS_BASE 0x210 5462306a36Sopenharmony_ci#define CMD_Q_INT_STATUS_BASE 0x214 5562306a36Sopenharmony_ci#define CMD_Q_STATUS_INCR 0x20 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define CMD_Q_CACHE_BASE 0x228 5862306a36Sopenharmony_ci#define CMD_Q_CACHE_INC 0x20 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define CMD_Q_ERROR(__qs) ((__qs) & 0x0000003f) 6162306a36Sopenharmony_ci#define CMD_Q_DEPTH(__qs) (((__qs) >> 12) & 0x0000000f) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* ------------------------ CCP Version 5 Specifics ------------------------ */ 6462306a36Sopenharmony_ci#define CMD5_QUEUE_MASK_OFFSET 0x00 6562306a36Sopenharmony_ci#define CMD5_QUEUE_PRIO_OFFSET 0x04 6662306a36Sopenharmony_ci#define CMD5_REQID_CONFIG_OFFSET 0x08 6762306a36Sopenharmony_ci#define CMD5_CMD_TIMEOUT_OFFSET 0x10 6862306a36Sopenharmony_ci#define LSB_PUBLIC_MASK_LO_OFFSET 0x18 6962306a36Sopenharmony_ci#define LSB_PUBLIC_MASK_HI_OFFSET 0x1C 7062306a36Sopenharmony_ci#define LSB_PRIVATE_MASK_LO_OFFSET 0x20 7162306a36Sopenharmony_ci#define LSB_PRIVATE_MASK_HI_OFFSET 0x24 7262306a36Sopenharmony_ci#define CMD5_PSP_CCP_VERSION 0x100 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define CMD5_Q_CONTROL_BASE 0x0000 7562306a36Sopenharmony_ci#define CMD5_Q_TAIL_LO_BASE 0x0004 7662306a36Sopenharmony_ci#define CMD5_Q_HEAD_LO_BASE 0x0008 7762306a36Sopenharmony_ci#define CMD5_Q_INT_ENABLE_BASE 0x000C 7862306a36Sopenharmony_ci#define CMD5_Q_INTERRUPT_STATUS_BASE 0x0010 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define CMD5_Q_STATUS_BASE 0x0100 8162306a36Sopenharmony_ci#define CMD5_Q_INT_STATUS_BASE 0x0104 8262306a36Sopenharmony_ci#define CMD5_Q_DMA_STATUS_BASE 0x0108 8362306a36Sopenharmony_ci#define CMD5_Q_DMA_READ_STATUS_BASE 0x010C 8462306a36Sopenharmony_ci#define CMD5_Q_DMA_WRITE_STATUS_BASE 0x0110 8562306a36Sopenharmony_ci#define CMD5_Q_ABORT_BASE 0x0114 8662306a36Sopenharmony_ci#define CMD5_Q_AX_CACHE_BASE 0x0118 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define CMD5_CONFIG_0_OFFSET 0x6000 8962306a36Sopenharmony_ci#define CMD5_TRNG_CTL_OFFSET 0x6008 9062306a36Sopenharmony_ci#define CMD5_AES_MASK_OFFSET 0x6010 9162306a36Sopenharmony_ci#define CMD5_CLK_GATE_CTL_OFFSET 0x603C 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* Address offset between two virtual queue registers */ 9462306a36Sopenharmony_ci#define CMD5_Q_STATUS_INCR 0x1000 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* Bit masks */ 9762306a36Sopenharmony_ci#define CMD5_Q_RUN 0x1 9862306a36Sopenharmony_ci#define CMD5_Q_HALT 0x2 9962306a36Sopenharmony_ci#define CMD5_Q_MEM_LOCATION 0x4 10062306a36Sopenharmony_ci#define CMD5_Q_SIZE 0x1F 10162306a36Sopenharmony_ci#define CMD5_Q_SHIFT 3 10262306a36Sopenharmony_ci#define COMMANDS_PER_QUEUE 16 10362306a36Sopenharmony_ci#define QUEUE_SIZE_VAL ((ffs(COMMANDS_PER_QUEUE) - 2) & \ 10462306a36Sopenharmony_ci CMD5_Q_SIZE) 10562306a36Sopenharmony_ci#define Q_PTR_MASK (2 << (QUEUE_SIZE_VAL + 5) - 1) 10662306a36Sopenharmony_ci#define Q_DESC_SIZE sizeof(struct ccp5_desc) 10762306a36Sopenharmony_ci#define Q_SIZE(n) (COMMANDS_PER_QUEUE*(n)) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define INT_COMPLETION 0x1 11062306a36Sopenharmony_ci#define INT_ERROR 0x2 11162306a36Sopenharmony_ci#define INT_QUEUE_STOPPED 0x4 11262306a36Sopenharmony_ci#define INT_EMPTY_QUEUE 0x8 11362306a36Sopenharmony_ci#define SUPPORTED_INTERRUPTS (INT_COMPLETION | INT_ERROR) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define LSB_REGION_WIDTH 5 11662306a36Sopenharmony_ci#define MAX_LSB_CNT 8 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define LSB_SIZE 16 11962306a36Sopenharmony_ci#define LSB_ITEM_SIZE 32 12062306a36Sopenharmony_ci#define PLSB_MAP_SIZE (LSB_SIZE) 12162306a36Sopenharmony_ci#define SLSB_MAP_SIZE (MAX_LSB_CNT * LSB_SIZE) 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#define LSB_ENTRY_NUMBER(LSB_ADDR) (LSB_ADDR / LSB_ITEM_SIZE) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* ------------------------ CCP Version 3 Specifics ------------------------ */ 12662306a36Sopenharmony_ci#define REQ0_WAIT_FOR_WRITE 0x00000004 12762306a36Sopenharmony_ci#define REQ0_INT_ON_COMPLETE 0x00000002 12862306a36Sopenharmony_ci#define REQ0_STOP_ON_COMPLETE 0x00000001 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#define REQ0_CMD_Q_SHIFT 9 13162306a36Sopenharmony_ci#define REQ0_JOBID_SHIFT 3 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/****** REQ1 Related Values ******/ 13462306a36Sopenharmony_ci#define REQ1_PROTECT_SHIFT 27 13562306a36Sopenharmony_ci#define REQ1_ENGINE_SHIFT 23 13662306a36Sopenharmony_ci#define REQ1_KEY_KSB_SHIFT 2 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci#define REQ1_EOM 0x00000002 13962306a36Sopenharmony_ci#define REQ1_INIT 0x00000001 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* AES Related Values */ 14262306a36Sopenharmony_ci#define REQ1_AES_TYPE_SHIFT 21 14362306a36Sopenharmony_ci#define REQ1_AES_MODE_SHIFT 18 14462306a36Sopenharmony_ci#define REQ1_AES_ACTION_SHIFT 17 14562306a36Sopenharmony_ci#define REQ1_AES_CFB_SIZE_SHIFT 10 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/* XTS-AES Related Values */ 14862306a36Sopenharmony_ci#define REQ1_XTS_AES_SIZE_SHIFT 10 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* SHA Related Values */ 15162306a36Sopenharmony_ci#define REQ1_SHA_TYPE_SHIFT 21 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* RSA Related Values */ 15462306a36Sopenharmony_ci#define REQ1_RSA_MOD_SIZE_SHIFT 10 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/* Pass-Through Related Values */ 15762306a36Sopenharmony_ci#define REQ1_PT_BW_SHIFT 12 15862306a36Sopenharmony_ci#define REQ1_PT_BS_SHIFT 10 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/* ECC Related Values */ 16162306a36Sopenharmony_ci#define REQ1_ECC_AFFINE_CONVERT 0x00200000 16262306a36Sopenharmony_ci#define REQ1_ECC_FUNCTION_SHIFT 18 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/****** REQ4 Related Values ******/ 16562306a36Sopenharmony_ci#define REQ4_KSB_SHIFT 18 16662306a36Sopenharmony_ci#define REQ4_MEMTYPE_SHIFT 16 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/****** REQ6 Related Values ******/ 16962306a36Sopenharmony_ci#define REQ6_MEMTYPE_SHIFT 16 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci/****** Key Storage Block ******/ 17262306a36Sopenharmony_ci#define KSB_START 77 17362306a36Sopenharmony_ci#define KSB_END 127 17462306a36Sopenharmony_ci#define KSB_COUNT (KSB_END - KSB_START + 1) 17562306a36Sopenharmony_ci#define CCP_SB_BITS 256 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci#define CCP_JOBID_MASK 0x0000003f 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* ------------------------ General CCP Defines ------------------------ */ 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#define CCP_DMA_DFLT 0x0 18262306a36Sopenharmony_ci#define CCP_DMA_PRIV 0x1 18362306a36Sopenharmony_ci#define CCP_DMA_PUB 0x2 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#define CCP_DMAPOOL_MAX_SIZE 64 18662306a36Sopenharmony_ci#define CCP_DMAPOOL_ALIGN BIT(5) 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci#define CCP_REVERSE_BUF_SIZE 64 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci#define CCP_AES_KEY_SB_COUNT 1 19162306a36Sopenharmony_ci#define CCP_AES_CTX_SB_COUNT 1 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci#define CCP_XTS_AES_KEY_SB_COUNT 1 19462306a36Sopenharmony_ci#define CCP5_XTS_AES_KEY_SB_COUNT 2 19562306a36Sopenharmony_ci#define CCP_XTS_AES_CTX_SB_COUNT 1 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#define CCP_DES3_KEY_SB_COUNT 1 19862306a36Sopenharmony_ci#define CCP_DES3_CTX_SB_COUNT 1 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#define CCP_SHA_SB_COUNT 1 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#define CCP_RSA_MAX_WIDTH 4096 20362306a36Sopenharmony_ci#define CCP5_RSA_MAX_WIDTH 16384 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci#define CCP_PASSTHRU_BLOCKSIZE 256 20662306a36Sopenharmony_ci#define CCP_PASSTHRU_MASKSIZE 32 20762306a36Sopenharmony_ci#define CCP_PASSTHRU_SB_COUNT 1 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */ 21062306a36Sopenharmony_ci#define CCP_ECC_MAX_OPERANDS 6 21162306a36Sopenharmony_ci#define CCP_ECC_MAX_OUTPUTS 3 21262306a36Sopenharmony_ci#define CCP_ECC_SRC_BUF_SIZE 448 21362306a36Sopenharmony_ci#define CCP_ECC_DST_BUF_SIZE 192 21462306a36Sopenharmony_ci#define CCP_ECC_OPERAND_SIZE 64 21562306a36Sopenharmony_ci#define CCP_ECC_OUTPUT_SIZE 64 21662306a36Sopenharmony_ci#define CCP_ECC_RESULT_OFFSET 60 21762306a36Sopenharmony_ci#define CCP_ECC_RESULT_SUCCESS 0x0001 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci#define CCP_SB_BYTES 32 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistruct ccp_op; 22262306a36Sopenharmony_cistruct ccp_device; 22362306a36Sopenharmony_cistruct ccp_cmd; 22462306a36Sopenharmony_cistruct ccp_fns; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistruct ccp_dma_cmd { 22762306a36Sopenharmony_ci struct list_head entry; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci struct ccp_cmd ccp_cmd; 23062306a36Sopenharmony_ci}; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistruct ccp_dma_desc { 23362306a36Sopenharmony_ci struct list_head entry; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci struct ccp_device *ccp; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci struct list_head pending; 23862306a36Sopenharmony_ci struct list_head active; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci enum dma_status status; 24162306a36Sopenharmony_ci struct dma_async_tx_descriptor tx_desc; 24262306a36Sopenharmony_ci size_t len; 24362306a36Sopenharmony_ci}; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistruct ccp_dma_chan { 24662306a36Sopenharmony_ci struct ccp_device *ccp; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci spinlock_t lock; 24962306a36Sopenharmony_ci struct list_head created; 25062306a36Sopenharmony_ci struct list_head pending; 25162306a36Sopenharmony_ci struct list_head active; 25262306a36Sopenharmony_ci struct list_head complete; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci struct tasklet_struct cleanup_tasklet; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci enum dma_status status; 25762306a36Sopenharmony_ci struct dma_chan dma_chan; 25862306a36Sopenharmony_ci}; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistruct ccp_cmd_queue { 26162306a36Sopenharmony_ci struct ccp_device *ccp; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Queue identifier */ 26462306a36Sopenharmony_ci u32 id; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* Queue dma pool */ 26762306a36Sopenharmony_ci struct dma_pool *dma_pool; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* Queue base address (not neccessarily aligned)*/ 27062306a36Sopenharmony_ci struct ccp5_desc *qbase; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* Aligned queue start address (per requirement) */ 27362306a36Sopenharmony_ci struct mutex q_mutex ____cacheline_aligned; 27462306a36Sopenharmony_ci unsigned int qidx; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* Version 5 has different requirements for queue memory */ 27762306a36Sopenharmony_ci unsigned int qsize; 27862306a36Sopenharmony_ci dma_addr_t qbase_dma; 27962306a36Sopenharmony_ci dma_addr_t qdma_tail; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* Per-queue reserved storage block(s) */ 28262306a36Sopenharmony_ci u32 sb_key; 28362306a36Sopenharmony_ci u32 sb_ctx; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* Bitmap of LSBs that can be accessed by this queue */ 28662306a36Sopenharmony_ci DECLARE_BITMAP(lsbmask, MAX_LSB_CNT); 28762306a36Sopenharmony_ci /* Private LSB that is assigned to this queue, or -1 if none. 28862306a36Sopenharmony_ci * Bitmap for my private LSB, unused otherwise 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_ci int lsb; 29162306a36Sopenharmony_ci DECLARE_BITMAP(lsbmap, PLSB_MAP_SIZE); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* Queue processing thread */ 29462306a36Sopenharmony_ci struct task_struct *kthread; 29562306a36Sopenharmony_ci unsigned int active; 29662306a36Sopenharmony_ci unsigned int suspended; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* Number of free command slots available */ 29962306a36Sopenharmony_ci unsigned int free_slots; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* Interrupt masks */ 30262306a36Sopenharmony_ci u32 int_ok; 30362306a36Sopenharmony_ci u32 int_err; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* Register addresses for queue */ 30662306a36Sopenharmony_ci void __iomem *reg_control; 30762306a36Sopenharmony_ci void __iomem *reg_tail_lo; 30862306a36Sopenharmony_ci void __iomem *reg_head_lo; 30962306a36Sopenharmony_ci void __iomem *reg_int_enable; 31062306a36Sopenharmony_ci void __iomem *reg_interrupt_status; 31162306a36Sopenharmony_ci void __iomem *reg_status; 31262306a36Sopenharmony_ci void __iomem *reg_int_status; 31362306a36Sopenharmony_ci void __iomem *reg_dma_status; 31462306a36Sopenharmony_ci void __iomem *reg_dma_read_status; 31562306a36Sopenharmony_ci void __iomem *reg_dma_write_status; 31662306a36Sopenharmony_ci u32 qcontrol; /* Cached control register */ 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci /* Status values from job */ 31962306a36Sopenharmony_ci u32 int_status; 32062306a36Sopenharmony_ci u32 q_status; 32162306a36Sopenharmony_ci u32 q_int_status; 32262306a36Sopenharmony_ci u32 cmd_error; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* Interrupt wait queue */ 32562306a36Sopenharmony_ci wait_queue_head_t int_queue; 32662306a36Sopenharmony_ci unsigned int int_rcvd; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci /* Per-queue Statistics */ 32962306a36Sopenharmony_ci unsigned long total_ops; 33062306a36Sopenharmony_ci unsigned long total_aes_ops; 33162306a36Sopenharmony_ci unsigned long total_xts_aes_ops; 33262306a36Sopenharmony_ci unsigned long total_3des_ops; 33362306a36Sopenharmony_ci unsigned long total_sha_ops; 33462306a36Sopenharmony_ci unsigned long total_rsa_ops; 33562306a36Sopenharmony_ci unsigned long total_pt_ops; 33662306a36Sopenharmony_ci unsigned long total_ecc_ops; 33762306a36Sopenharmony_ci} ____cacheline_aligned; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistruct ccp_device { 34062306a36Sopenharmony_ci struct list_head entry; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci struct ccp_vdata *vdata; 34362306a36Sopenharmony_ci unsigned int ord; 34462306a36Sopenharmony_ci char name[MAX_CCP_NAME_LEN]; 34562306a36Sopenharmony_ci char rngname[MAX_CCP_NAME_LEN]; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci struct device *dev; 34862306a36Sopenharmony_ci struct sp_device *sp; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* Bus specific device information 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci void *dev_specific; 35362306a36Sopenharmony_ci unsigned int qim; 35462306a36Sopenharmony_ci unsigned int irq; 35562306a36Sopenharmony_ci bool use_tasklet; 35662306a36Sopenharmony_ci struct tasklet_struct irq_tasklet; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* I/O area used for device communication. The register mapping 35962306a36Sopenharmony_ci * starts at an offset into the mapped bar. 36062306a36Sopenharmony_ci * The CMD_REQx registers and the Delete_Cmd_Queue_Job register 36162306a36Sopenharmony_ci * need to be protected while a command queue thread is accessing 36262306a36Sopenharmony_ci * them. 36362306a36Sopenharmony_ci */ 36462306a36Sopenharmony_ci struct mutex req_mutex ____cacheline_aligned; 36562306a36Sopenharmony_ci void __iomem *io_regs; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /* Master lists that all cmds are queued on. Because there can be 36862306a36Sopenharmony_ci * more than one CCP command queue that can process a cmd a separate 36962306a36Sopenharmony_ci * backlog list is needed so that the backlog completion call 37062306a36Sopenharmony_ci * completes before the cmd is available for execution. 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_ci spinlock_t cmd_lock ____cacheline_aligned; 37362306a36Sopenharmony_ci unsigned int cmd_count; 37462306a36Sopenharmony_ci struct list_head cmd; 37562306a36Sopenharmony_ci struct list_head backlog; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* The command queues. These represent the queues available on the 37862306a36Sopenharmony_ci * CCP that are available for processing cmds 37962306a36Sopenharmony_ci */ 38062306a36Sopenharmony_ci struct ccp_cmd_queue cmd_q[MAX_HW_QUEUES]; 38162306a36Sopenharmony_ci unsigned int cmd_q_count; 38262306a36Sopenharmony_ci unsigned int max_q_count; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* Support for the CCP True RNG 38562306a36Sopenharmony_ci */ 38662306a36Sopenharmony_ci struct hwrng hwrng; 38762306a36Sopenharmony_ci unsigned int hwrng_retries; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /* Support for the CCP DMA capabilities 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ci struct dma_device dma_dev; 39262306a36Sopenharmony_ci struct ccp_dma_chan *ccp_dma_chan; 39362306a36Sopenharmony_ci struct kmem_cache *dma_cmd_cache; 39462306a36Sopenharmony_ci struct kmem_cache *dma_desc_cache; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* A counter used to generate job-ids for cmds submitted to the CCP 39762306a36Sopenharmony_ci */ 39862306a36Sopenharmony_ci atomic_t current_id ____cacheline_aligned; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci /* The v3 CCP uses key storage blocks (SB) to maintain context for 40162306a36Sopenharmony_ci * certain operations. To prevent multiple cmds from using the same 40262306a36Sopenharmony_ci * SB range a command queue reserves an SB range for the duration of 40362306a36Sopenharmony_ci * the cmd. Each queue, will however, reserve 2 SB blocks for 40462306a36Sopenharmony_ci * operations that only require single SB entries (eg. AES context/iv 40562306a36Sopenharmony_ci * and key) in order to avoid allocation contention. This will reserve 40662306a36Sopenharmony_ci * at most 10 SB entries, leaving 40 SB entries available for dynamic 40762306a36Sopenharmony_ci * allocation. 40862306a36Sopenharmony_ci * 40962306a36Sopenharmony_ci * The v5 CCP Local Storage Block (LSB) is broken up into 8 41062306a36Sopenharmony_ci * memrory ranges, each of which can be enabled for access by one 41162306a36Sopenharmony_ci * or more queues. Device initialization takes this into account, 41262306a36Sopenharmony_ci * and attempts to assign one region for exclusive use by each 41362306a36Sopenharmony_ci * available queue; the rest are then aggregated as "public" use. 41462306a36Sopenharmony_ci * If there are fewer regions than queues, all regions are shared 41562306a36Sopenharmony_ci * amongst all queues. 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_ci struct mutex sb_mutex ____cacheline_aligned; 41862306a36Sopenharmony_ci DECLARE_BITMAP(sb, KSB_COUNT); 41962306a36Sopenharmony_ci wait_queue_head_t sb_queue; 42062306a36Sopenharmony_ci unsigned int sb_avail; 42162306a36Sopenharmony_ci unsigned int sb_count; 42262306a36Sopenharmony_ci u32 sb_start; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* Bitmap of shared LSBs, if any */ 42562306a36Sopenharmony_ci DECLARE_BITMAP(lsbmap, SLSB_MAP_SIZE); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* Suspend support */ 42862306a36Sopenharmony_ci unsigned int suspending; 42962306a36Sopenharmony_ci wait_queue_head_t suspend_queue; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* DMA caching attribute support */ 43262306a36Sopenharmony_ci unsigned int axcache; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci /* Device Statistics */ 43562306a36Sopenharmony_ci unsigned long total_interrupts; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* DebugFS info */ 43862306a36Sopenharmony_ci struct dentry *debugfs_instance; 43962306a36Sopenharmony_ci}; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cienum ccp_memtype { 44262306a36Sopenharmony_ci CCP_MEMTYPE_SYSTEM = 0, 44362306a36Sopenharmony_ci CCP_MEMTYPE_SB, 44462306a36Sopenharmony_ci CCP_MEMTYPE_LOCAL, 44562306a36Sopenharmony_ci CCP_MEMTYPE__LAST, 44662306a36Sopenharmony_ci}; 44762306a36Sopenharmony_ci#define CCP_MEMTYPE_LSB CCP_MEMTYPE_KSB 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistruct ccp_dma_info { 45162306a36Sopenharmony_ci dma_addr_t address; 45262306a36Sopenharmony_ci unsigned int offset; 45362306a36Sopenharmony_ci unsigned int length; 45462306a36Sopenharmony_ci enum dma_data_direction dir; 45562306a36Sopenharmony_ci} __packed __aligned(4); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistruct ccp_dm_workarea { 45862306a36Sopenharmony_ci struct device *dev; 45962306a36Sopenharmony_ci struct dma_pool *dma_pool; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci u8 *address; 46262306a36Sopenharmony_ci struct ccp_dma_info dma; 46362306a36Sopenharmony_ci unsigned int length; 46462306a36Sopenharmony_ci}; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistruct ccp_sg_workarea { 46762306a36Sopenharmony_ci struct scatterlist *sg; 46862306a36Sopenharmony_ci int nents; 46962306a36Sopenharmony_ci unsigned int sg_used; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci struct scatterlist *dma_sg; 47262306a36Sopenharmony_ci struct scatterlist *dma_sg_head; 47362306a36Sopenharmony_ci struct device *dma_dev; 47462306a36Sopenharmony_ci unsigned int dma_count; 47562306a36Sopenharmony_ci enum dma_data_direction dma_dir; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci u64 bytes_left; 47862306a36Sopenharmony_ci}; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistruct ccp_data { 48162306a36Sopenharmony_ci struct ccp_sg_workarea sg_wa; 48262306a36Sopenharmony_ci struct ccp_dm_workarea dm_wa; 48362306a36Sopenharmony_ci}; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistruct ccp_mem { 48662306a36Sopenharmony_ci enum ccp_memtype type; 48762306a36Sopenharmony_ci union { 48862306a36Sopenharmony_ci struct ccp_dma_info dma; 48962306a36Sopenharmony_ci u32 sb; 49062306a36Sopenharmony_ci } u; 49162306a36Sopenharmony_ci}; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cistruct ccp_aes_op { 49462306a36Sopenharmony_ci enum ccp_aes_type type; 49562306a36Sopenharmony_ci enum ccp_aes_mode mode; 49662306a36Sopenharmony_ci enum ccp_aes_action action; 49762306a36Sopenharmony_ci unsigned int size; 49862306a36Sopenharmony_ci}; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistruct ccp_xts_aes_op { 50162306a36Sopenharmony_ci enum ccp_aes_type type; 50262306a36Sopenharmony_ci enum ccp_aes_action action; 50362306a36Sopenharmony_ci enum ccp_xts_aes_unit_size unit_size; 50462306a36Sopenharmony_ci}; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistruct ccp_des3_op { 50762306a36Sopenharmony_ci enum ccp_des3_type type; 50862306a36Sopenharmony_ci enum ccp_des3_mode mode; 50962306a36Sopenharmony_ci enum ccp_des3_action action; 51062306a36Sopenharmony_ci}; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistruct ccp_sha_op { 51362306a36Sopenharmony_ci enum ccp_sha_type type; 51462306a36Sopenharmony_ci u64 msg_bits; 51562306a36Sopenharmony_ci}; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistruct ccp_rsa_op { 51862306a36Sopenharmony_ci u32 mod_size; 51962306a36Sopenharmony_ci u32 input_len; 52062306a36Sopenharmony_ci}; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_cistruct ccp_passthru_op { 52362306a36Sopenharmony_ci enum ccp_passthru_bitwise bit_mod; 52462306a36Sopenharmony_ci enum ccp_passthru_byteswap byte_swap; 52562306a36Sopenharmony_ci}; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistruct ccp_ecc_op { 52862306a36Sopenharmony_ci enum ccp_ecc_function function; 52962306a36Sopenharmony_ci}; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistruct ccp_op { 53262306a36Sopenharmony_ci struct ccp_cmd_queue *cmd_q; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci u32 jobid; 53562306a36Sopenharmony_ci u32 ioc; 53662306a36Sopenharmony_ci u32 soc; 53762306a36Sopenharmony_ci u32 sb_key; 53862306a36Sopenharmony_ci u32 sb_ctx; 53962306a36Sopenharmony_ci u32 init; 54062306a36Sopenharmony_ci u32 eom; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci struct ccp_mem src; 54362306a36Sopenharmony_ci struct ccp_mem dst; 54462306a36Sopenharmony_ci struct ccp_mem exp; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci union { 54762306a36Sopenharmony_ci struct ccp_aes_op aes; 54862306a36Sopenharmony_ci struct ccp_xts_aes_op xts; 54962306a36Sopenharmony_ci struct ccp_des3_op des3; 55062306a36Sopenharmony_ci struct ccp_sha_op sha; 55162306a36Sopenharmony_ci struct ccp_rsa_op rsa; 55262306a36Sopenharmony_ci struct ccp_passthru_op passthru; 55362306a36Sopenharmony_ci struct ccp_ecc_op ecc; 55462306a36Sopenharmony_ci } u; 55562306a36Sopenharmony_ci}; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic inline u32 ccp_addr_lo(struct ccp_dma_info *info) 55862306a36Sopenharmony_ci{ 55962306a36Sopenharmony_ci return lower_32_bits(info->address + info->offset); 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic inline u32 ccp_addr_hi(struct ccp_dma_info *info) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci return upper_32_bits(info->address + info->offset) & 0x0000ffff; 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci/** 56862306a36Sopenharmony_ci * descriptor for version 5 CPP commands 56962306a36Sopenharmony_ci * 8 32-bit words: 57062306a36Sopenharmony_ci * word 0: function; engine; control bits 57162306a36Sopenharmony_ci * word 1: length of source data 57262306a36Sopenharmony_ci * word 2: low 32 bits of source pointer 57362306a36Sopenharmony_ci * word 3: upper 16 bits of source pointer; source memory type 57462306a36Sopenharmony_ci * word 4: low 32 bits of destination pointer 57562306a36Sopenharmony_ci * word 5: upper 16 bits of destination pointer; destination memory type 57662306a36Sopenharmony_ci * word 6: low 32 bits of key pointer 57762306a36Sopenharmony_ci * word 7: upper 16 bits of key pointer; key memory type 57862306a36Sopenharmony_ci */ 57962306a36Sopenharmony_cistruct dword0 { 58062306a36Sopenharmony_ci unsigned int soc:1; 58162306a36Sopenharmony_ci unsigned int ioc:1; 58262306a36Sopenharmony_ci unsigned int rsvd1:1; 58362306a36Sopenharmony_ci unsigned int init:1; 58462306a36Sopenharmony_ci unsigned int eom:1; /* AES/SHA only */ 58562306a36Sopenharmony_ci unsigned int function:15; 58662306a36Sopenharmony_ci unsigned int engine:4; 58762306a36Sopenharmony_ci unsigned int prot:1; 58862306a36Sopenharmony_ci unsigned int rsvd2:7; 58962306a36Sopenharmony_ci}; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistruct dword3 { 59262306a36Sopenharmony_ci unsigned int src_hi:16; 59362306a36Sopenharmony_ci unsigned int src_mem:2; 59462306a36Sopenharmony_ci unsigned int lsb_cxt_id:8; 59562306a36Sopenharmony_ci unsigned int rsvd1:5; 59662306a36Sopenharmony_ci unsigned int fixed:1; 59762306a36Sopenharmony_ci}; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ciunion dword4 { 60062306a36Sopenharmony_ci u32 dst_lo; /* NON-SHA */ 60162306a36Sopenharmony_ci u32 sha_len_lo; /* SHA */ 60262306a36Sopenharmony_ci}; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ciunion dword5 { 60562306a36Sopenharmony_ci struct { 60662306a36Sopenharmony_ci unsigned int dst_hi:16; 60762306a36Sopenharmony_ci unsigned int dst_mem:2; 60862306a36Sopenharmony_ci unsigned int rsvd1:13; 60962306a36Sopenharmony_ci unsigned int fixed:1; 61062306a36Sopenharmony_ci } fields; 61162306a36Sopenharmony_ci u32 sha_len_hi; 61262306a36Sopenharmony_ci}; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistruct dword7 { 61562306a36Sopenharmony_ci unsigned int key_hi:16; 61662306a36Sopenharmony_ci unsigned int key_mem:2; 61762306a36Sopenharmony_ci unsigned int rsvd1:14; 61862306a36Sopenharmony_ci}; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistruct ccp5_desc { 62162306a36Sopenharmony_ci struct dword0 dw0; 62262306a36Sopenharmony_ci u32 length; 62362306a36Sopenharmony_ci u32 src_lo; 62462306a36Sopenharmony_ci struct dword3 dw3; 62562306a36Sopenharmony_ci union dword4 dw4; 62662306a36Sopenharmony_ci union dword5 dw5; 62762306a36Sopenharmony_ci u32 key_lo; 62862306a36Sopenharmony_ci struct dword7 dw7; 62962306a36Sopenharmony_ci}; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_civoid ccp_add_device(struct ccp_device *ccp); 63262306a36Sopenharmony_civoid ccp_del_device(struct ccp_device *ccp); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ciextern void ccp_log_error(struct ccp_device *, unsigned int); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistruct ccp_device *ccp_alloc_struct(struct sp_device *sp); 63762306a36Sopenharmony_cibool ccp_queues_suspended(struct ccp_device *ccp); 63862306a36Sopenharmony_ciint ccp_cmd_queue_thread(void *data); 63962306a36Sopenharmony_ciint ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ciint ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ciint ccp_register_rng(struct ccp_device *ccp); 64462306a36Sopenharmony_civoid ccp_unregister_rng(struct ccp_device *ccp); 64562306a36Sopenharmony_ciint ccp_dmaengine_register(struct ccp_device *ccp); 64662306a36Sopenharmony_civoid ccp_dmaengine_unregister(struct ccp_device *ccp); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_civoid ccp5_debugfs_setup(struct ccp_device *ccp); 64962306a36Sopenharmony_civoid ccp5_debugfs_destroy(void); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci/* Structure for computation functions that are device-specific */ 65262306a36Sopenharmony_cistruct ccp_actions { 65362306a36Sopenharmony_ci int (*aes)(struct ccp_op *); 65462306a36Sopenharmony_ci int (*xts_aes)(struct ccp_op *); 65562306a36Sopenharmony_ci int (*des3)(struct ccp_op *); 65662306a36Sopenharmony_ci int (*sha)(struct ccp_op *); 65762306a36Sopenharmony_ci int (*rsa)(struct ccp_op *); 65862306a36Sopenharmony_ci int (*passthru)(struct ccp_op *); 65962306a36Sopenharmony_ci int (*ecc)(struct ccp_op *); 66062306a36Sopenharmony_ci u32 (*sballoc)(struct ccp_cmd_queue *, unsigned int); 66162306a36Sopenharmony_ci void (*sbfree)(struct ccp_cmd_queue *, unsigned int, unsigned int); 66262306a36Sopenharmony_ci unsigned int (*get_free_slots)(struct ccp_cmd_queue *); 66362306a36Sopenharmony_ci int (*init)(struct ccp_device *); 66462306a36Sopenharmony_ci void (*destroy)(struct ccp_device *); 66562306a36Sopenharmony_ci irqreturn_t (*irqhandler)(int, void *); 66662306a36Sopenharmony_ci}; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ciextern const struct ccp_vdata ccpv3_platform; 66962306a36Sopenharmony_ciextern const struct ccp_vdata ccpv3; 67062306a36Sopenharmony_ciextern const struct ccp_vdata ccpv5a; 67162306a36Sopenharmony_ciextern const struct ccp_vdata ccpv5b; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci#endif 674