1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun /* Copyright(c) 2019 Intel Corporation. All rights rsvd. */ 3*4882a593Smuzhiyun #ifndef _IDXD_REGISTERS_H_ 4*4882a593Smuzhiyun #define _IDXD_REGISTERS_H_ 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun /* PCI Config */ 7*4882a593Smuzhiyun #define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #define IDXD_MMIO_BAR 0 10*4882a593Smuzhiyun #define IDXD_WQ_BAR 2 11*4882a593Smuzhiyun #define IDXD_PORTAL_SIZE PAGE_SIZE 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun /* MMIO Device BAR0 Registers */ 14*4882a593Smuzhiyun #define IDXD_VER_OFFSET 0x00 15*4882a593Smuzhiyun #define IDXD_VER_MAJOR_MASK 0xf0 16*4882a593Smuzhiyun #define IDXD_VER_MINOR_MASK 0x0f 17*4882a593Smuzhiyun #define GET_IDXD_VER_MAJOR(x) (((x) & IDXD_VER_MAJOR_MASK) >> 4) 18*4882a593Smuzhiyun #define GET_IDXD_VER_MINOR(x) ((x) & IDXD_VER_MINOR_MASK) 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun union gen_cap_reg { 21*4882a593Smuzhiyun struct { 22*4882a593Smuzhiyun u64 block_on_fault:1; 23*4882a593Smuzhiyun u64 overlap_copy:1; 24*4882a593Smuzhiyun u64 cache_control_mem:1; 25*4882a593Smuzhiyun u64 cache_control_cache:1; 26*4882a593Smuzhiyun u64 rsvd:3; 27*4882a593Smuzhiyun u64 int_handle_req:1; 28*4882a593Smuzhiyun u64 dest_readback:1; 29*4882a593Smuzhiyun u64 drain_readback:1; 30*4882a593Smuzhiyun u64 rsvd2:6; 31*4882a593Smuzhiyun u64 max_xfer_shift:5; 32*4882a593Smuzhiyun u64 max_batch_shift:4; 33*4882a593Smuzhiyun u64 max_ims_mult:6; 34*4882a593Smuzhiyun u64 config_en:1; 35*4882a593Smuzhiyun u64 max_descs_per_engine:8; 36*4882a593Smuzhiyun u64 rsvd3:24; 37*4882a593Smuzhiyun }; 38*4882a593Smuzhiyun u64 bits; 39*4882a593Smuzhiyun } __packed; 40*4882a593Smuzhiyun #define IDXD_GENCAP_OFFSET 0x10 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun union wq_cap_reg { 43*4882a593Smuzhiyun struct { 44*4882a593Smuzhiyun u64 total_wq_size:16; 45*4882a593Smuzhiyun u64 num_wqs:8; 46*4882a593Smuzhiyun u64 wqcfg_size:4; 47*4882a593Smuzhiyun u64 rsvd:20; 48*4882a593Smuzhiyun u64 shared_mode:1; 49*4882a593Smuzhiyun u64 dedicated_mode:1; 50*4882a593Smuzhiyun u64 rsvd2:1; 51*4882a593Smuzhiyun u64 priority:1; 52*4882a593Smuzhiyun u64 occupancy:1; 53*4882a593Smuzhiyun u64 occupancy_int:1; 54*4882a593Smuzhiyun u64 rsvd3:10; 55*4882a593Smuzhiyun }; 56*4882a593Smuzhiyun u64 bits; 57*4882a593Smuzhiyun } __packed; 58*4882a593Smuzhiyun #define IDXD_WQCAP_OFFSET 0x20 59*4882a593Smuzhiyun #define IDXD_WQCFG_MIN 5 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun union group_cap_reg { 62*4882a593Smuzhiyun struct { 63*4882a593Smuzhiyun u64 num_groups:8; 64*4882a593Smuzhiyun u64 total_tokens:8; 65*4882a593Smuzhiyun u64 token_en:1; 66*4882a593Smuzhiyun u64 token_limit:1; 67*4882a593Smuzhiyun u64 rsvd:46; 68*4882a593Smuzhiyun }; 69*4882a593Smuzhiyun u64 bits; 70*4882a593Smuzhiyun } __packed; 71*4882a593Smuzhiyun #define IDXD_GRPCAP_OFFSET 0x30 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun union engine_cap_reg { 74*4882a593Smuzhiyun struct { 75*4882a593Smuzhiyun u64 num_engines:8; 76*4882a593Smuzhiyun u64 rsvd:56; 77*4882a593Smuzhiyun }; 78*4882a593Smuzhiyun u64 bits; 79*4882a593Smuzhiyun } __packed; 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun #define IDXD_ENGCAP_OFFSET 0x38 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun #define IDXD_OPCAP_NOOP 0x0001 84*4882a593Smuzhiyun #define IDXD_OPCAP_BATCH 0x0002 85*4882a593Smuzhiyun #define IDXD_OPCAP_MEMMOVE 0x0008 86*4882a593Smuzhiyun struct opcap { 87*4882a593Smuzhiyun u64 bits[4]; 88*4882a593Smuzhiyun }; 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun #define IDXD_OPCAP_OFFSET 0x40 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun #define IDXD_TABLE_OFFSET 0x60 93*4882a593Smuzhiyun union offsets_reg { 94*4882a593Smuzhiyun struct { 95*4882a593Smuzhiyun u64 grpcfg:16; 96*4882a593Smuzhiyun u64 wqcfg:16; 97*4882a593Smuzhiyun u64 msix_perm:16; 98*4882a593Smuzhiyun u64 ims:16; 99*4882a593Smuzhiyun u64 perfmon:16; 100*4882a593Smuzhiyun u64 rsvd:48; 101*4882a593Smuzhiyun }; 102*4882a593Smuzhiyun u64 bits[2]; 103*4882a593Smuzhiyun } __packed; 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun #define IDXD_GENCFG_OFFSET 0x80 106*4882a593Smuzhiyun union gencfg_reg { 107*4882a593Smuzhiyun struct { 108*4882a593Smuzhiyun u32 token_limit:8; 109*4882a593Smuzhiyun u32 rsvd:4; 110*4882a593Smuzhiyun u32 user_int_en:1; 111*4882a593Smuzhiyun u32 rsvd2:19; 112*4882a593Smuzhiyun }; 113*4882a593Smuzhiyun u32 bits; 114*4882a593Smuzhiyun } __packed; 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun #define IDXD_GENCTRL_OFFSET 0x88 117*4882a593Smuzhiyun union genctrl_reg { 118*4882a593Smuzhiyun struct { 119*4882a593Smuzhiyun u32 softerr_int_en:1; 120*4882a593Smuzhiyun u32 rsvd:31; 121*4882a593Smuzhiyun }; 122*4882a593Smuzhiyun u32 bits; 123*4882a593Smuzhiyun } __packed; 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun #define IDXD_GENSTATS_OFFSET 0x90 126*4882a593Smuzhiyun union gensts_reg { 127*4882a593Smuzhiyun struct { 128*4882a593Smuzhiyun u32 state:2; 129*4882a593Smuzhiyun u32 reset_type:2; 130*4882a593Smuzhiyun u32 rsvd:28; 131*4882a593Smuzhiyun }; 132*4882a593Smuzhiyun u32 bits; 133*4882a593Smuzhiyun } __packed; 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun enum idxd_device_status_state { 136*4882a593Smuzhiyun IDXD_DEVICE_STATE_DISABLED = 0, 137*4882a593Smuzhiyun IDXD_DEVICE_STATE_ENABLED, 138*4882a593Smuzhiyun IDXD_DEVICE_STATE_DRAIN, 139*4882a593Smuzhiyun IDXD_DEVICE_STATE_HALT, 140*4882a593Smuzhiyun }; 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun enum idxd_device_reset_type { 143*4882a593Smuzhiyun IDXD_DEVICE_RESET_SOFTWARE = 0, 144*4882a593Smuzhiyun IDXD_DEVICE_RESET_FLR, 145*4882a593Smuzhiyun IDXD_DEVICE_RESET_WARM, 146*4882a593Smuzhiyun IDXD_DEVICE_RESET_COLD, 147*4882a593Smuzhiyun }; 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun #define IDXD_INTCAUSE_OFFSET 0x98 150*4882a593Smuzhiyun #define IDXD_INTC_ERR 0x01 151*4882a593Smuzhiyun #define IDXD_INTC_CMD 0x02 152*4882a593Smuzhiyun #define IDXD_INTC_OCCUPY 0x04 153*4882a593Smuzhiyun #define IDXD_INTC_PERFMON_OVFL 0x08 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun #define IDXD_CMD_OFFSET 0xa0 156*4882a593Smuzhiyun union idxd_command_reg { 157*4882a593Smuzhiyun struct { 158*4882a593Smuzhiyun u32 operand:20; 159*4882a593Smuzhiyun u32 cmd:5; 160*4882a593Smuzhiyun u32 rsvd:6; 161*4882a593Smuzhiyun u32 int_req:1; 162*4882a593Smuzhiyun }; 163*4882a593Smuzhiyun u32 bits; 164*4882a593Smuzhiyun } __packed; 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun enum idxd_cmd { 167*4882a593Smuzhiyun IDXD_CMD_ENABLE_DEVICE = 1, 168*4882a593Smuzhiyun IDXD_CMD_DISABLE_DEVICE, 169*4882a593Smuzhiyun IDXD_CMD_DRAIN_ALL, 170*4882a593Smuzhiyun IDXD_CMD_ABORT_ALL, 171*4882a593Smuzhiyun IDXD_CMD_RESET_DEVICE, 172*4882a593Smuzhiyun IDXD_CMD_ENABLE_WQ, 173*4882a593Smuzhiyun IDXD_CMD_DISABLE_WQ, 174*4882a593Smuzhiyun IDXD_CMD_DRAIN_WQ, 175*4882a593Smuzhiyun IDXD_CMD_ABORT_WQ, 176*4882a593Smuzhiyun IDXD_CMD_RESET_WQ, 177*4882a593Smuzhiyun IDXD_CMD_DRAIN_PASID, 178*4882a593Smuzhiyun IDXD_CMD_ABORT_PASID, 179*4882a593Smuzhiyun IDXD_CMD_REQUEST_INT_HANDLE, 180*4882a593Smuzhiyun }; 181*4882a593Smuzhiyun 182*4882a593Smuzhiyun #define IDXD_CMDSTS_OFFSET 0xa8 183*4882a593Smuzhiyun union cmdsts_reg { 184*4882a593Smuzhiyun struct { 185*4882a593Smuzhiyun u8 err; 186*4882a593Smuzhiyun u16 result; 187*4882a593Smuzhiyun u8 rsvd:7; 188*4882a593Smuzhiyun u8 active:1; 189*4882a593Smuzhiyun }; 190*4882a593Smuzhiyun u32 bits; 191*4882a593Smuzhiyun } __packed; 192*4882a593Smuzhiyun #define IDXD_CMDSTS_ACTIVE 0x80000000 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun enum idxd_cmdsts_err { 195*4882a593Smuzhiyun IDXD_CMDSTS_SUCCESS = 0, 196*4882a593Smuzhiyun IDXD_CMDSTS_INVAL_CMD, 197*4882a593Smuzhiyun IDXD_CMDSTS_INVAL_WQIDX, 198*4882a593Smuzhiyun IDXD_CMDSTS_HW_ERR, 199*4882a593Smuzhiyun /* enable device errors */ 200*4882a593Smuzhiyun IDXD_CMDSTS_ERR_DEV_ENABLED = 0x10, 201*4882a593Smuzhiyun IDXD_CMDSTS_ERR_CONFIG, 202*4882a593Smuzhiyun IDXD_CMDSTS_ERR_BUSMASTER_EN, 203*4882a593Smuzhiyun IDXD_CMDSTS_ERR_PASID_INVAL, 204*4882a593Smuzhiyun IDXD_CMDSTS_ERR_WQ_SIZE_ERANGE, 205*4882a593Smuzhiyun IDXD_CMDSTS_ERR_GRP_CONFIG, 206*4882a593Smuzhiyun IDXD_CMDSTS_ERR_GRP_CONFIG2, 207*4882a593Smuzhiyun IDXD_CMDSTS_ERR_GRP_CONFIG3, 208*4882a593Smuzhiyun IDXD_CMDSTS_ERR_GRP_CONFIG4, 209*4882a593Smuzhiyun /* enable wq errors */ 210*4882a593Smuzhiyun IDXD_CMDSTS_ERR_DEV_NOTEN = 0x20, 211*4882a593Smuzhiyun IDXD_CMDSTS_ERR_WQ_ENABLED, 212*4882a593Smuzhiyun IDXD_CMDSTS_ERR_WQ_SIZE, 213*4882a593Smuzhiyun IDXD_CMDSTS_ERR_WQ_PRIOR, 214*4882a593Smuzhiyun IDXD_CMDSTS_ERR_WQ_MODE, 215*4882a593Smuzhiyun IDXD_CMDSTS_ERR_BOF_EN, 216*4882a593Smuzhiyun IDXD_CMDSTS_ERR_PASID_EN, 217*4882a593Smuzhiyun IDXD_CMDSTS_ERR_MAX_BATCH_SIZE, 218*4882a593Smuzhiyun IDXD_CMDSTS_ERR_MAX_XFER_SIZE, 219*4882a593Smuzhiyun /* disable device errors */ 220*4882a593Smuzhiyun IDXD_CMDSTS_ERR_DIS_DEV_EN = 0x31, 221*4882a593Smuzhiyun /* disable WQ, drain WQ, abort WQ, reset WQ */ 222*4882a593Smuzhiyun IDXD_CMDSTS_ERR_DEV_NOT_EN, 223*4882a593Smuzhiyun /* request interrupt handle */ 224*4882a593Smuzhiyun IDXD_CMDSTS_ERR_INVAL_INT_IDX = 0x41, 225*4882a593Smuzhiyun IDXD_CMDSTS_ERR_NO_HANDLE, 226*4882a593Smuzhiyun }; 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun #define IDXD_SWERR_OFFSET 0xc0 229*4882a593Smuzhiyun #define IDXD_SWERR_VALID 0x00000001 230*4882a593Smuzhiyun #define IDXD_SWERR_OVERFLOW 0x00000002 231*4882a593Smuzhiyun #define IDXD_SWERR_ACK (IDXD_SWERR_VALID | IDXD_SWERR_OVERFLOW) 232*4882a593Smuzhiyun union sw_err_reg { 233*4882a593Smuzhiyun struct { 234*4882a593Smuzhiyun u64 valid:1; 235*4882a593Smuzhiyun u64 overflow:1; 236*4882a593Smuzhiyun u64 desc_valid:1; 237*4882a593Smuzhiyun u64 wq_idx_valid:1; 238*4882a593Smuzhiyun u64 batch:1; 239*4882a593Smuzhiyun u64 fault_rw:1; 240*4882a593Smuzhiyun u64 priv:1; 241*4882a593Smuzhiyun u64 rsvd:1; 242*4882a593Smuzhiyun u64 error:8; 243*4882a593Smuzhiyun u64 wq_idx:8; 244*4882a593Smuzhiyun u64 rsvd2:8; 245*4882a593Smuzhiyun u64 operation:8; 246*4882a593Smuzhiyun u64 pasid:20; 247*4882a593Smuzhiyun u64 rsvd3:4; 248*4882a593Smuzhiyun 249*4882a593Smuzhiyun u64 batch_idx:16; 250*4882a593Smuzhiyun u64 rsvd4:16; 251*4882a593Smuzhiyun u64 invalid_flags:32; 252*4882a593Smuzhiyun 253*4882a593Smuzhiyun u64 fault_addr; 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun u64 rsvd5; 256*4882a593Smuzhiyun }; 257*4882a593Smuzhiyun u64 bits[4]; 258*4882a593Smuzhiyun } __packed; 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun union msix_perm { 261*4882a593Smuzhiyun struct { 262*4882a593Smuzhiyun u32 rsvd:2; 263*4882a593Smuzhiyun u32 ignore:1; 264*4882a593Smuzhiyun u32 pasid_en:1; 265*4882a593Smuzhiyun u32 rsvd2:8; 266*4882a593Smuzhiyun u32 pasid:20; 267*4882a593Smuzhiyun }; 268*4882a593Smuzhiyun u32 bits; 269*4882a593Smuzhiyun } __packed; 270*4882a593Smuzhiyun 271*4882a593Smuzhiyun union group_flags { 272*4882a593Smuzhiyun struct { 273*4882a593Smuzhiyun u32 tc_a:3; 274*4882a593Smuzhiyun u32 tc_b:3; 275*4882a593Smuzhiyun u32 rsvd:1; 276*4882a593Smuzhiyun u32 use_token_limit:1; 277*4882a593Smuzhiyun u32 tokens_reserved:8; 278*4882a593Smuzhiyun u32 rsvd2:4; 279*4882a593Smuzhiyun u32 tokens_allowed:8; 280*4882a593Smuzhiyun u32 rsvd3:4; 281*4882a593Smuzhiyun }; 282*4882a593Smuzhiyun u32 bits; 283*4882a593Smuzhiyun } __packed; 284*4882a593Smuzhiyun 285*4882a593Smuzhiyun struct grpcfg { 286*4882a593Smuzhiyun u64 wqs[4]; 287*4882a593Smuzhiyun u64 engines; 288*4882a593Smuzhiyun union group_flags flags; 289*4882a593Smuzhiyun } __packed; 290*4882a593Smuzhiyun 291*4882a593Smuzhiyun union wqcfg { 292*4882a593Smuzhiyun struct { 293*4882a593Smuzhiyun /* bytes 0-3 */ 294*4882a593Smuzhiyun u16 wq_size; 295*4882a593Smuzhiyun u16 rsvd; 296*4882a593Smuzhiyun 297*4882a593Smuzhiyun /* bytes 4-7 */ 298*4882a593Smuzhiyun u16 wq_thresh; 299*4882a593Smuzhiyun u16 rsvd1; 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun /* bytes 8-11 */ 302*4882a593Smuzhiyun u32 mode:1; /* shared or dedicated */ 303*4882a593Smuzhiyun u32 bof:1; /* block on fault */ 304*4882a593Smuzhiyun u32 rsvd2:2; 305*4882a593Smuzhiyun u32 priority:4; 306*4882a593Smuzhiyun u32 pasid:20; 307*4882a593Smuzhiyun u32 pasid_en:1; 308*4882a593Smuzhiyun u32 priv:1; 309*4882a593Smuzhiyun u32 rsvd3:2; 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun /* bytes 12-15 */ 312*4882a593Smuzhiyun u32 max_xfer_shift:5; 313*4882a593Smuzhiyun u32 max_batch_shift:4; 314*4882a593Smuzhiyun u32 rsvd4:23; 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun /* bytes 16-19 */ 317*4882a593Smuzhiyun u16 occupancy_inth; 318*4882a593Smuzhiyun u16 occupancy_table_sel:1; 319*4882a593Smuzhiyun u16 rsvd5:15; 320*4882a593Smuzhiyun 321*4882a593Smuzhiyun /* bytes 20-23 */ 322*4882a593Smuzhiyun u16 occupancy_limit; 323*4882a593Smuzhiyun u16 occupancy_int_en:1; 324*4882a593Smuzhiyun u16 rsvd6:15; 325*4882a593Smuzhiyun 326*4882a593Smuzhiyun /* bytes 24-27 */ 327*4882a593Smuzhiyun u16 occupancy; 328*4882a593Smuzhiyun u16 occupancy_int:1; 329*4882a593Smuzhiyun u16 rsvd7:12; 330*4882a593Smuzhiyun u16 mode_support:1; 331*4882a593Smuzhiyun u16 wq_state:2; 332*4882a593Smuzhiyun 333*4882a593Smuzhiyun /* bytes 28-31 */ 334*4882a593Smuzhiyun u32 rsvd8; 335*4882a593Smuzhiyun }; 336*4882a593Smuzhiyun u32 bits[8]; 337*4882a593Smuzhiyun } __packed; 338*4882a593Smuzhiyun 339*4882a593Smuzhiyun /* 340*4882a593Smuzhiyun * This macro calculates the offset into the WQCFG register 341*4882a593Smuzhiyun * idxd - struct idxd * 342*4882a593Smuzhiyun * n - wq id 343*4882a593Smuzhiyun * ofs - the index of the 32b dword for the config register 344*4882a593Smuzhiyun * 345*4882a593Smuzhiyun * The WQCFG register block is divided into groups per each wq. The n index 346*4882a593Smuzhiyun * allows us to move to the register group that's for that particular wq. 347*4882a593Smuzhiyun * Each register is 32bits. The ofs gives us the number of register to access. 348*4882a593Smuzhiyun */ 349*4882a593Smuzhiyun #define WQCFG_OFFSET(_idxd_dev, n, ofs) \ 350*4882a593Smuzhiyun ({\ 351*4882a593Smuzhiyun typeof(_idxd_dev) __idxd_dev = (_idxd_dev); \ 352*4882a593Smuzhiyun (__idxd_dev)->wqcfg_offset + (n) * (__idxd_dev)->wqcfg_size + sizeof(u32) * (ofs); \ 353*4882a593Smuzhiyun }) 354*4882a593Smuzhiyun 355*4882a593Smuzhiyun #define WQCFG_STRIDES(_idxd_dev) ((_idxd_dev)->wqcfg_size / sizeof(u32)) 356*4882a593Smuzhiyun 357*4882a593Smuzhiyun #endif 358