1*63b94509STom Lendacky /* 2*63b94509STom Lendacky * AMD Cryptographic Coprocessor (CCP) driver 3*63b94509STom Lendacky * 4*63b94509STom Lendacky * Copyright (C) 2013 Advanced Micro Devices, Inc. 5*63b94509STom Lendacky * 6*63b94509STom Lendacky * Author: Tom Lendacky <thomas.lendacky@amd.com> 7*63b94509STom Lendacky * 8*63b94509STom Lendacky * This program is free software; you can redistribute it and/or modify 9*63b94509STom Lendacky * it under the terms of the GNU General Public License version 2 as 10*63b94509STom Lendacky * published by the Free Software Foundation. 11*63b94509STom Lendacky */ 12*63b94509STom Lendacky 13*63b94509STom Lendacky #ifndef __CCP_DEV_H__ 14*63b94509STom Lendacky #define __CCP_DEV_H__ 15*63b94509STom Lendacky 16*63b94509STom Lendacky #include <linux/device.h> 17*63b94509STom Lendacky #include <linux/pci.h> 18*63b94509STom Lendacky #include <linux/spinlock.h> 19*63b94509STom Lendacky #include <linux/mutex.h> 20*63b94509STom Lendacky #include <linux/list.h> 21*63b94509STom Lendacky #include <linux/wait.h> 22*63b94509STom Lendacky #include <linux/dmapool.h> 23*63b94509STom Lendacky #include <linux/hw_random.h> 24*63b94509STom Lendacky 25*63b94509STom Lendacky 26*63b94509STom Lendacky #define IO_OFFSET 0x20000 27*63b94509STom Lendacky 28*63b94509STom Lendacky #define MAX_DMAPOOL_NAME_LEN 32 29*63b94509STom Lendacky 30*63b94509STom Lendacky #define MAX_HW_QUEUES 5 31*63b94509STom Lendacky #define MAX_CMD_QLEN 100 32*63b94509STom Lendacky 33*63b94509STom Lendacky #define TRNG_RETRIES 10 34*63b94509STom Lendacky 35*63b94509STom Lendacky 36*63b94509STom Lendacky /****** Register Mappings ******/ 37*63b94509STom Lendacky #define Q_MASK_REG 0x000 38*63b94509STom Lendacky #define TRNG_OUT_REG 0x00c 39*63b94509STom Lendacky #define IRQ_MASK_REG 0x040 40*63b94509STom Lendacky #define IRQ_STATUS_REG 0x200 41*63b94509STom Lendacky 42*63b94509STom Lendacky #define DEL_CMD_Q_JOB 0x124 43*63b94509STom Lendacky #define DEL_Q_ACTIVE 0x00000200 44*63b94509STom Lendacky #define DEL_Q_ID_SHIFT 6 45*63b94509STom Lendacky 46*63b94509STom Lendacky #define CMD_REQ0 0x180 47*63b94509STom Lendacky #define CMD_REQ_INCR 0x04 48*63b94509STom Lendacky 49*63b94509STom Lendacky #define CMD_Q_STATUS_BASE 0x210 50*63b94509STom Lendacky #define CMD_Q_INT_STATUS_BASE 0x214 51*63b94509STom Lendacky #define CMD_Q_STATUS_INCR 0x20 52*63b94509STom Lendacky 53*63b94509STom Lendacky #define CMD_Q_CACHE 0x228 54*63b94509STom Lendacky #define CMD_Q_CACHE_INC 0x20 55*63b94509STom Lendacky 56*63b94509STom Lendacky #define CMD_Q_ERROR(__qs) ((__qs) & 0x0000003f); 57*63b94509STom Lendacky #define CMD_Q_DEPTH(__qs) (((__qs) >> 12) & 0x0000000f); 58*63b94509STom Lendacky 59*63b94509STom Lendacky /****** REQ0 Related Values ******/ 60*63b94509STom Lendacky #define REQ0_WAIT_FOR_WRITE 0x00000004 61*63b94509STom Lendacky #define REQ0_INT_ON_COMPLETE 0x00000002 62*63b94509STom Lendacky #define REQ0_STOP_ON_COMPLETE 0x00000001 63*63b94509STom Lendacky 64*63b94509STom Lendacky #define REQ0_CMD_Q_SHIFT 9 65*63b94509STom Lendacky #define REQ0_JOBID_SHIFT 3 66*63b94509STom Lendacky 67*63b94509STom Lendacky /****** REQ1 Related Values ******/ 68*63b94509STom Lendacky #define REQ1_PROTECT_SHIFT 27 69*63b94509STom Lendacky #define REQ1_ENGINE_SHIFT 23 70*63b94509STom Lendacky #define REQ1_KEY_KSB_SHIFT 2 71*63b94509STom Lendacky 72*63b94509STom Lendacky #define REQ1_EOM 0x00000002 73*63b94509STom Lendacky #define REQ1_INIT 0x00000001 74*63b94509STom Lendacky 75*63b94509STom Lendacky /* AES Related Values */ 76*63b94509STom Lendacky #define REQ1_AES_TYPE_SHIFT 21 77*63b94509STom Lendacky #define REQ1_AES_MODE_SHIFT 18 78*63b94509STom Lendacky #define REQ1_AES_ACTION_SHIFT 17 79*63b94509STom Lendacky #define REQ1_AES_CFB_SIZE_SHIFT 10 80*63b94509STom Lendacky 81*63b94509STom Lendacky /* XTS-AES Related Values */ 82*63b94509STom Lendacky #define REQ1_XTS_AES_SIZE_SHIFT 10 83*63b94509STom Lendacky 84*63b94509STom Lendacky /* SHA Related Values */ 85*63b94509STom Lendacky #define REQ1_SHA_TYPE_SHIFT 21 86*63b94509STom Lendacky 87*63b94509STom Lendacky /* RSA Related Values */ 88*63b94509STom Lendacky #define REQ1_RSA_MOD_SIZE_SHIFT 10 89*63b94509STom Lendacky 90*63b94509STom Lendacky /* Pass-Through Related Values */ 91*63b94509STom Lendacky #define REQ1_PT_BW_SHIFT 12 92*63b94509STom Lendacky #define REQ1_PT_BS_SHIFT 10 93*63b94509STom Lendacky 94*63b94509STom Lendacky /* ECC Related Values */ 95*63b94509STom Lendacky #define REQ1_ECC_AFFINE_CONVERT 0x00200000 96*63b94509STom Lendacky #define REQ1_ECC_FUNCTION_SHIFT 18 97*63b94509STom Lendacky 98*63b94509STom Lendacky /****** REQ4 Related Values ******/ 99*63b94509STom Lendacky #define REQ4_KSB_SHIFT 18 100*63b94509STom Lendacky #define REQ4_MEMTYPE_SHIFT 16 101*63b94509STom Lendacky 102*63b94509STom Lendacky /****** REQ6 Related Values ******/ 103*63b94509STom Lendacky #define REQ6_MEMTYPE_SHIFT 16 104*63b94509STom Lendacky 105*63b94509STom Lendacky 106*63b94509STom Lendacky /****** Key Storage Block ******/ 107*63b94509STom Lendacky #define KSB_START 77 108*63b94509STom Lendacky #define KSB_END 127 109*63b94509STom Lendacky #define KSB_COUNT (KSB_END - KSB_START + 1) 110*63b94509STom Lendacky #define CCP_KSB_BITS 256 111*63b94509STom Lendacky #define CCP_KSB_BYTES 32 112*63b94509STom Lendacky 113*63b94509STom Lendacky #define CCP_JOBID_MASK 0x0000003f 114*63b94509STom Lendacky 115*63b94509STom Lendacky #define CCP_DMAPOOL_MAX_SIZE 64 116*63b94509STom Lendacky #define CCP_DMAPOOL_ALIGN (1 << 5) 117*63b94509STom Lendacky 118*63b94509STom Lendacky #define CCP_REVERSE_BUF_SIZE 64 119*63b94509STom Lendacky 120*63b94509STom Lendacky #define CCP_AES_KEY_KSB_COUNT 1 121*63b94509STom Lendacky #define CCP_AES_CTX_KSB_COUNT 1 122*63b94509STom Lendacky 123*63b94509STom Lendacky #define CCP_XTS_AES_KEY_KSB_COUNT 1 124*63b94509STom Lendacky #define CCP_XTS_AES_CTX_KSB_COUNT 1 125*63b94509STom Lendacky 126*63b94509STom Lendacky #define CCP_SHA_KSB_COUNT 1 127*63b94509STom Lendacky 128*63b94509STom Lendacky #define CCP_RSA_MAX_WIDTH 4096 129*63b94509STom Lendacky 130*63b94509STom Lendacky #define CCP_PASSTHRU_BLOCKSIZE 256 131*63b94509STom Lendacky #define CCP_PASSTHRU_MASKSIZE 32 132*63b94509STom Lendacky #define CCP_PASSTHRU_KSB_COUNT 1 133*63b94509STom Lendacky 134*63b94509STom Lendacky #define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */ 135*63b94509STom Lendacky #define CCP_ECC_MAX_OPERANDS 6 136*63b94509STom Lendacky #define CCP_ECC_MAX_OUTPUTS 3 137*63b94509STom Lendacky #define CCP_ECC_SRC_BUF_SIZE 448 138*63b94509STom Lendacky #define CCP_ECC_DST_BUF_SIZE 192 139*63b94509STom Lendacky #define CCP_ECC_OPERAND_SIZE 64 140*63b94509STom Lendacky #define CCP_ECC_OUTPUT_SIZE 64 141*63b94509STom Lendacky #define CCP_ECC_RESULT_OFFSET 60 142*63b94509STom Lendacky #define CCP_ECC_RESULT_SUCCESS 0x0001 143*63b94509STom Lendacky 144*63b94509STom Lendacky 145*63b94509STom Lendacky struct ccp_device; 146*63b94509STom Lendacky struct ccp_cmd; 147*63b94509STom Lendacky 148*63b94509STom Lendacky struct ccp_cmd_queue { 149*63b94509STom Lendacky struct ccp_device *ccp; 150*63b94509STom Lendacky 151*63b94509STom Lendacky /* Queue identifier */ 152*63b94509STom Lendacky u32 id; 153*63b94509STom Lendacky 154*63b94509STom Lendacky /* Queue dma pool */ 155*63b94509STom Lendacky struct dma_pool *dma_pool; 156*63b94509STom Lendacky 157*63b94509STom Lendacky /* Queue reserved KSB regions */ 158*63b94509STom Lendacky u32 ksb_key; 159*63b94509STom Lendacky u32 ksb_ctx; 160*63b94509STom Lendacky 161*63b94509STom Lendacky /* Queue processing thread */ 162*63b94509STom Lendacky struct task_struct *kthread; 163*63b94509STom Lendacky unsigned int active; 164*63b94509STom Lendacky unsigned int suspended; 165*63b94509STom Lendacky 166*63b94509STom Lendacky /* Number of free command slots available */ 167*63b94509STom Lendacky unsigned int free_slots; 168*63b94509STom Lendacky 169*63b94509STom Lendacky /* Interrupt masks */ 170*63b94509STom Lendacky u32 int_ok; 171*63b94509STom Lendacky u32 int_err; 172*63b94509STom Lendacky 173*63b94509STom Lendacky /* Register addresses for queue */ 174*63b94509STom Lendacky void __iomem *reg_status; 175*63b94509STom Lendacky void __iomem *reg_int_status; 176*63b94509STom Lendacky 177*63b94509STom Lendacky /* Status values from job */ 178*63b94509STom Lendacky u32 int_status; 179*63b94509STom Lendacky u32 q_status; 180*63b94509STom Lendacky u32 q_int_status; 181*63b94509STom Lendacky u32 cmd_error; 182*63b94509STom Lendacky 183*63b94509STom Lendacky /* Interrupt wait queue */ 184*63b94509STom Lendacky wait_queue_head_t int_queue; 185*63b94509STom Lendacky unsigned int int_rcvd; 186*63b94509STom Lendacky } ____cacheline_aligned; 187*63b94509STom Lendacky 188*63b94509STom Lendacky struct ccp_device { 189*63b94509STom Lendacky struct device *dev; 190*63b94509STom Lendacky 191*63b94509STom Lendacky /* 192*63b94509STom Lendacky * Bus specific device information 193*63b94509STom Lendacky */ 194*63b94509STom Lendacky void *dev_specific; 195*63b94509STom Lendacky int (*get_irq)(struct ccp_device *ccp); 196*63b94509STom Lendacky void (*free_irq)(struct ccp_device *ccp); 197*63b94509STom Lendacky 198*63b94509STom Lendacky /* 199*63b94509STom Lendacky * I/O area used for device communication. The register mapping 200*63b94509STom Lendacky * starts at an offset into the mapped bar. 201*63b94509STom Lendacky * The CMD_REQx registers and the Delete_Cmd_Queue_Job register 202*63b94509STom Lendacky * need to be protected while a command queue thread is accessing 203*63b94509STom Lendacky * them. 204*63b94509STom Lendacky */ 205*63b94509STom Lendacky struct mutex req_mutex ____cacheline_aligned; 206*63b94509STom Lendacky void __iomem *io_map; 207*63b94509STom Lendacky void __iomem *io_regs; 208*63b94509STom Lendacky 209*63b94509STom Lendacky /* 210*63b94509STom Lendacky * Master lists that all cmds are queued on. Because there can be 211*63b94509STom Lendacky * more than one CCP command queue that can process a cmd a separate 212*63b94509STom Lendacky * backlog list is neeeded so that the backlog completion call 213*63b94509STom Lendacky * completes before the cmd is available for execution. 214*63b94509STom Lendacky */ 215*63b94509STom Lendacky spinlock_t cmd_lock ____cacheline_aligned; 216*63b94509STom Lendacky unsigned int cmd_count; 217*63b94509STom Lendacky struct list_head cmd; 218*63b94509STom Lendacky struct list_head backlog; 219*63b94509STom Lendacky 220*63b94509STom Lendacky /* 221*63b94509STom Lendacky * The command queues. These represent the queues available on the 222*63b94509STom Lendacky * CCP that are available for processing cmds 223*63b94509STom Lendacky */ 224*63b94509STom Lendacky struct ccp_cmd_queue cmd_q[MAX_HW_QUEUES]; 225*63b94509STom Lendacky unsigned int cmd_q_count; 226*63b94509STom Lendacky 227*63b94509STom Lendacky /* 228*63b94509STom Lendacky * Support for the CCP True RNG 229*63b94509STom Lendacky */ 230*63b94509STom Lendacky struct hwrng hwrng; 231*63b94509STom Lendacky unsigned int hwrng_retries; 232*63b94509STom Lendacky 233*63b94509STom Lendacky /* 234*63b94509STom Lendacky * A counter used to generate job-ids for cmds submitted to the CCP 235*63b94509STom Lendacky */ 236*63b94509STom Lendacky atomic_t current_id ____cacheline_aligned; 237*63b94509STom Lendacky 238*63b94509STom Lendacky /* 239*63b94509STom Lendacky * The CCP uses key storage blocks (KSB) to maintain context for certain 240*63b94509STom Lendacky * operations. To prevent multiple cmds from using the same KSB range 241*63b94509STom Lendacky * a command queue reserves a KSB range for the duration of the cmd. 242*63b94509STom Lendacky * Each queue, will however, reserve 2 KSB blocks for operations that 243*63b94509STom Lendacky * only require single KSB entries (eg. AES context/iv and key) in order 244*63b94509STom Lendacky * to avoid allocation contention. This will reserve at most 10 KSB 245*63b94509STom Lendacky * entries, leaving 40 KSB entries available for dynamic allocation. 246*63b94509STom Lendacky */ 247*63b94509STom Lendacky struct mutex ksb_mutex ____cacheline_aligned; 248*63b94509STom Lendacky DECLARE_BITMAP(ksb, KSB_COUNT); 249*63b94509STom Lendacky wait_queue_head_t ksb_queue; 250*63b94509STom Lendacky unsigned int ksb_avail; 251*63b94509STom Lendacky unsigned int ksb_count; 252*63b94509STom Lendacky u32 ksb_start; 253*63b94509STom Lendacky 254*63b94509STom Lendacky /* Suspend support */ 255*63b94509STom Lendacky unsigned int suspending; 256*63b94509STom Lendacky wait_queue_head_t suspend_queue; 257*63b94509STom Lendacky }; 258*63b94509STom Lendacky 259*63b94509STom Lendacky 260*63b94509STom Lendacky int ccp_pci_init(void); 261*63b94509STom Lendacky void ccp_pci_exit(void); 262*63b94509STom Lendacky 263*63b94509STom Lendacky struct ccp_device *ccp_alloc_struct(struct device *dev); 264*63b94509STom Lendacky int ccp_init(struct ccp_device *ccp); 265*63b94509STom Lendacky void ccp_destroy(struct ccp_device *ccp); 266*63b94509STom Lendacky bool ccp_queues_suspended(struct ccp_device *ccp); 267*63b94509STom Lendacky 268*63b94509STom Lendacky irqreturn_t ccp_irq_handler(int irq, void *data); 269*63b94509STom Lendacky 270*63b94509STom Lendacky int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd); 271*63b94509STom Lendacky 272*63b94509STom Lendacky #endif 273