162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2019 HiSilicon Limited. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/acpi.h> 562306a36Sopenharmony_ci#include <linux/bitops.h> 662306a36Sopenharmony_ci#include <linux/debugfs.h> 762306a36Sopenharmony_ci#include <linux/init.h> 862306a36Sopenharmony_ci#include <linux/io.h> 962306a36Sopenharmony_ci#include <linux/iommu.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/pci.h> 1362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1462306a36Sopenharmony_ci#include <linux/seq_file.h> 1562306a36Sopenharmony_ci#include <linux/topology.h> 1662306a36Sopenharmony_ci#include <linux/uacce.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "sec.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define SEC_VF_NUM 63 2162306a36Sopenharmony_ci#define SEC_QUEUE_NUM_V1 4096 2262306a36Sopenharmony_ci#define PCI_DEVICE_ID_HUAWEI_SEC_PF 0xa255 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define SEC_BD_ERR_CHK_EN0 0xEFFFFFFF 2562306a36Sopenharmony_ci#define SEC_BD_ERR_CHK_EN1 0x7ffff7fd 2662306a36Sopenharmony_ci#define SEC_BD_ERR_CHK_EN3 0xffffbfff 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define SEC_SQE_SIZE 128 2962306a36Sopenharmony_ci#define SEC_PF_DEF_Q_NUM 256 3062306a36Sopenharmony_ci#define SEC_PF_DEF_Q_BASE 0 3162306a36Sopenharmony_ci#define SEC_CTX_Q_NUM_DEF 2 3262306a36Sopenharmony_ci#define SEC_CTX_Q_NUM_MAX 32 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define SEC_CTRL_CNT_CLR_CE 0x301120 3562306a36Sopenharmony_ci#define SEC_CTRL_CNT_CLR_CE_BIT BIT(0) 3662306a36Sopenharmony_ci#define SEC_CORE_INT_SOURCE 0x301010 3762306a36Sopenharmony_ci#define SEC_CORE_INT_MASK 0x301000 3862306a36Sopenharmony_ci#define SEC_CORE_INT_STATUS 0x301008 3962306a36Sopenharmony_ci#define SEC_CORE_SRAM_ECC_ERR_INFO 0x301C14 4062306a36Sopenharmony_ci#define SEC_ECC_NUM 16 4162306a36Sopenharmony_ci#define SEC_ECC_MASH 0xFF 4262306a36Sopenharmony_ci#define SEC_CORE_INT_DISABLE 0x0 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define SEC_RAS_CE_REG 0x301050 4562306a36Sopenharmony_ci#define SEC_RAS_FE_REG 0x301054 4662306a36Sopenharmony_ci#define SEC_RAS_NFE_REG 0x301058 4762306a36Sopenharmony_ci#define SEC_RAS_FE_ENB_MSK 0x0 4862306a36Sopenharmony_ci#define SEC_OOO_SHUTDOWN_SEL 0x301014 4962306a36Sopenharmony_ci#define SEC_RAS_DISABLE 0x0 5062306a36Sopenharmony_ci#define SEC_MEM_START_INIT_REG 0x301100 5162306a36Sopenharmony_ci#define SEC_MEM_INIT_DONE_REG 0x301104 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* clock gating */ 5462306a36Sopenharmony_ci#define SEC_CONTROL_REG 0x301200 5562306a36Sopenharmony_ci#define SEC_DYNAMIC_GATE_REG 0x30121c 5662306a36Sopenharmony_ci#define SEC_CORE_AUTO_GATE 0x30212c 5762306a36Sopenharmony_ci#define SEC_DYNAMIC_GATE_EN 0x7fff 5862306a36Sopenharmony_ci#define SEC_CORE_AUTO_GATE_EN GENMASK(3, 0) 5962306a36Sopenharmony_ci#define SEC_CLK_GATE_ENABLE BIT(3) 6062306a36Sopenharmony_ci#define SEC_CLK_GATE_DISABLE (~BIT(3)) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define SEC_TRNG_EN_SHIFT 8 6362306a36Sopenharmony_ci#define SEC_AXI_SHUTDOWN_ENABLE BIT(12) 6462306a36Sopenharmony_ci#define SEC_AXI_SHUTDOWN_DISABLE 0xFFFFEFFF 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define SEC_INTERFACE_USER_CTRL0_REG 0x301220 6762306a36Sopenharmony_ci#define SEC_INTERFACE_USER_CTRL1_REG 0x301224 6862306a36Sopenharmony_ci#define SEC_SAA_EN_REG 0x301270 6962306a36Sopenharmony_ci#define SEC_BD_ERR_CHK_EN_REG0 0x301380 7062306a36Sopenharmony_ci#define SEC_BD_ERR_CHK_EN_REG1 0x301384 7162306a36Sopenharmony_ci#define SEC_BD_ERR_CHK_EN_REG3 0x30138c 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define SEC_USER0_SMMU_NORMAL (BIT(23) | BIT(15)) 7462306a36Sopenharmony_ci#define SEC_USER1_SMMU_NORMAL (BIT(31) | BIT(23) | BIT(15) | BIT(7)) 7562306a36Sopenharmony_ci#define SEC_USER1_ENABLE_CONTEXT_SSV BIT(24) 7662306a36Sopenharmony_ci#define SEC_USER1_ENABLE_DATA_SSV BIT(16) 7762306a36Sopenharmony_ci#define SEC_USER1_WB_CONTEXT_SSV BIT(8) 7862306a36Sopenharmony_ci#define SEC_USER1_WB_DATA_SSV BIT(0) 7962306a36Sopenharmony_ci#define SEC_USER1_SVA_SET (SEC_USER1_ENABLE_CONTEXT_SSV | \ 8062306a36Sopenharmony_ci SEC_USER1_ENABLE_DATA_SSV | \ 8162306a36Sopenharmony_ci SEC_USER1_WB_CONTEXT_SSV | \ 8262306a36Sopenharmony_ci SEC_USER1_WB_DATA_SSV) 8362306a36Sopenharmony_ci#define SEC_USER1_SMMU_SVA (SEC_USER1_SMMU_NORMAL | SEC_USER1_SVA_SET) 8462306a36Sopenharmony_ci#define SEC_USER1_SMMU_MASK (~SEC_USER1_SVA_SET) 8562306a36Sopenharmony_ci#define SEC_INTERFACE_USER_CTRL0_REG_V3 0x302220 8662306a36Sopenharmony_ci#define SEC_INTERFACE_USER_CTRL1_REG_V3 0x302224 8762306a36Sopenharmony_ci#define SEC_USER1_SMMU_NORMAL_V3 (BIT(23) | BIT(17) | BIT(11) | BIT(5)) 8862306a36Sopenharmony_ci#define SEC_USER1_SMMU_MASK_V3 0xFF79E79E 8962306a36Sopenharmony_ci#define SEC_CORE_INT_STATUS_M_ECC BIT(2) 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define SEC_PREFETCH_CFG 0x301130 9262306a36Sopenharmony_ci#define SEC_SVA_TRANS 0x301EC4 9362306a36Sopenharmony_ci#define SEC_PREFETCH_ENABLE (~(BIT(0) | BIT(1) | BIT(11))) 9462306a36Sopenharmony_ci#define SEC_PREFETCH_DISABLE BIT(1) 9562306a36Sopenharmony_ci#define SEC_SVA_DISABLE_READY (BIT(7) | BIT(11)) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define SEC_DELAY_10_US 10 9862306a36Sopenharmony_ci#define SEC_POLL_TIMEOUT_US 1000 9962306a36Sopenharmony_ci#define SEC_DBGFS_VAL_MAX_LEN 20 10062306a36Sopenharmony_ci#define SEC_SINGLE_PORT_MAX_TRANS 0x2060 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#define SEC_SQE_MASK_OFFSET 64 10362306a36Sopenharmony_ci#define SEC_SQE_MASK_LEN 48 10462306a36Sopenharmony_ci#define SEC_SHAPER_TYPE_RATE 400 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define SEC_DFX_BASE 0x301000 10762306a36Sopenharmony_ci#define SEC_DFX_CORE 0x302100 10862306a36Sopenharmony_ci#define SEC_DFX_COMMON1 0x301600 10962306a36Sopenharmony_ci#define SEC_DFX_COMMON2 0x301C00 11062306a36Sopenharmony_ci#define SEC_DFX_BASE_LEN 0x9D 11162306a36Sopenharmony_ci#define SEC_DFX_CORE_LEN 0x32B 11262306a36Sopenharmony_ci#define SEC_DFX_COMMON1_LEN 0x45 11362306a36Sopenharmony_ci#define SEC_DFX_COMMON2_LEN 0xBA 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define SEC_ALG_BITMAP_SHIFT 32 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define SEC_CIPHER_BITMAP (GENMASK_ULL(5, 0) | GENMASK_ULL(16, 12) | \ 11862306a36Sopenharmony_ci GENMASK(24, 21)) 11962306a36Sopenharmony_ci#define SEC_DIGEST_BITMAP (GENMASK_ULL(11, 8) | GENMASK_ULL(20, 19) | \ 12062306a36Sopenharmony_ci GENMASK_ULL(42, 25)) 12162306a36Sopenharmony_ci#define SEC_AEAD_BITMAP (GENMASK_ULL(7, 6) | GENMASK_ULL(18, 17) | \ 12262306a36Sopenharmony_ci GENMASK_ULL(45, 43)) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistruct sec_hw_error { 12562306a36Sopenharmony_ci u32 int_msk; 12662306a36Sopenharmony_ci const char *msg; 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistruct sec_dfx_item { 13062306a36Sopenharmony_ci const char *name; 13162306a36Sopenharmony_ci u32 offset; 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic const char sec_name[] = "hisi_sec2"; 13562306a36Sopenharmony_cistatic struct dentry *sec_debugfs_root; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic struct hisi_qm_list sec_devices = { 13862306a36Sopenharmony_ci .register_to_crypto = sec_register_to_crypto, 13962306a36Sopenharmony_ci .unregister_from_crypto = sec_unregister_from_crypto, 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic const struct hisi_qm_cap_info sec_basic_info[] = { 14362306a36Sopenharmony_ci {SEC_QM_NFE_MASK_CAP, 0x3124, 0, GENMASK(31, 0), 0x0, 0x1C77, 0x7C77}, 14462306a36Sopenharmony_ci {SEC_QM_RESET_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0xC77, 0x6C77}, 14562306a36Sopenharmony_ci {SEC_QM_OOO_SHUTDOWN_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0x4, 0x6C77}, 14662306a36Sopenharmony_ci {SEC_QM_CE_MASK_CAP, 0x312C, 0, GENMASK(31, 0), 0x0, 0x8, 0x8}, 14762306a36Sopenharmony_ci {SEC_NFE_MASK_CAP, 0x3130, 0, GENMASK(31, 0), 0x0, 0x177, 0x60177}, 14862306a36Sopenharmony_ci {SEC_RESET_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x177, 0x177}, 14962306a36Sopenharmony_ci {SEC_OOO_SHUTDOWN_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x4, 0x177}, 15062306a36Sopenharmony_ci {SEC_CE_MASK_CAP, 0x3138, 0, GENMASK(31, 0), 0x0, 0x88, 0xC088}, 15162306a36Sopenharmony_ci {SEC_CLUSTER_NUM_CAP, 0x313c, 20, GENMASK(3, 0), 0x1, 0x1, 0x1}, 15262306a36Sopenharmony_ci {SEC_CORE_TYPE_NUM_CAP, 0x313c, 16, GENMASK(3, 0), 0x1, 0x1, 0x1}, 15362306a36Sopenharmony_ci {SEC_CORE_NUM_CAP, 0x313c, 8, GENMASK(7, 0), 0x4, 0x4, 0x4}, 15462306a36Sopenharmony_ci {SEC_CORES_PER_CLUSTER_NUM_CAP, 0x313c, 0, GENMASK(7, 0), 0x4, 0x4, 0x4}, 15562306a36Sopenharmony_ci {SEC_CORE_ENABLE_BITMAP, 0x3140, 32, GENMASK(31, 0), 0x17F, 0x17F, 0xF}, 15662306a36Sopenharmony_ci {SEC_DRV_ALG_BITMAP_LOW, 0x3144, 0, GENMASK(31, 0), 0x18050CB, 0x18050CB, 0x187F0FF}, 15762306a36Sopenharmony_ci {SEC_DRV_ALG_BITMAP_HIGH, 0x3148, 0, GENMASK(31, 0), 0x395C, 0x395C, 0x395C}, 15862306a36Sopenharmony_ci {SEC_DEV_ALG_BITMAP_LOW, 0x314c, 0, GENMASK(31, 0), 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, 15962306a36Sopenharmony_ci {SEC_DEV_ALG_BITMAP_HIGH, 0x3150, 0, GENMASK(31, 0), 0x3FFF, 0x3FFF, 0x3FFF}, 16062306a36Sopenharmony_ci {SEC_CORE1_ALG_BITMAP_LOW, 0x3154, 0, GENMASK(31, 0), 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, 16162306a36Sopenharmony_ci {SEC_CORE1_ALG_BITMAP_HIGH, 0x3158, 0, GENMASK(31, 0), 0x3FFF, 0x3FFF, 0x3FFF}, 16262306a36Sopenharmony_ci {SEC_CORE2_ALG_BITMAP_LOW, 0x315c, 0, GENMASK(31, 0), 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, 16362306a36Sopenharmony_ci {SEC_CORE2_ALG_BITMAP_HIGH, 0x3160, 0, GENMASK(31, 0), 0x3FFF, 0x3FFF, 0x3FFF}, 16462306a36Sopenharmony_ci {SEC_CORE3_ALG_BITMAP_LOW, 0x3164, 0, GENMASK(31, 0), 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, 16562306a36Sopenharmony_ci {SEC_CORE3_ALG_BITMAP_HIGH, 0x3168, 0, GENMASK(31, 0), 0x3FFF, 0x3FFF, 0x3FFF}, 16662306a36Sopenharmony_ci {SEC_CORE4_ALG_BITMAP_LOW, 0x316c, 0, GENMASK(31, 0), 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, 16762306a36Sopenharmony_ci {SEC_CORE4_ALG_BITMAP_HIGH, 0x3170, 0, GENMASK(31, 0), 0x3FFF, 0x3FFF, 0x3FFF}, 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic const u32 sec_pre_store_caps[] = { 17162306a36Sopenharmony_ci SEC_DRV_ALG_BITMAP_LOW, 17262306a36Sopenharmony_ci SEC_DRV_ALG_BITMAP_HIGH, 17362306a36Sopenharmony_ci SEC_DEV_ALG_BITMAP_LOW, 17462306a36Sopenharmony_ci SEC_DEV_ALG_BITMAP_HIGH, 17562306a36Sopenharmony_ci}; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic const struct qm_dev_alg sec_dev_algs[] = { { 17862306a36Sopenharmony_ci .alg_msk = SEC_CIPHER_BITMAP, 17962306a36Sopenharmony_ci .alg = "cipher\n", 18062306a36Sopenharmony_ci }, { 18162306a36Sopenharmony_ci .alg_msk = SEC_DIGEST_BITMAP, 18262306a36Sopenharmony_ci .alg = "digest\n", 18362306a36Sopenharmony_ci }, { 18462306a36Sopenharmony_ci .alg_msk = SEC_AEAD_BITMAP, 18562306a36Sopenharmony_ci .alg = "aead\n", 18662306a36Sopenharmony_ci }, 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic const struct sec_hw_error sec_hw_errors[] = { 19062306a36Sopenharmony_ci { 19162306a36Sopenharmony_ci .int_msk = BIT(0), 19262306a36Sopenharmony_ci .msg = "sec_axi_rresp_err_rint" 19362306a36Sopenharmony_ci }, 19462306a36Sopenharmony_ci { 19562306a36Sopenharmony_ci .int_msk = BIT(1), 19662306a36Sopenharmony_ci .msg = "sec_axi_bresp_err_rint" 19762306a36Sopenharmony_ci }, 19862306a36Sopenharmony_ci { 19962306a36Sopenharmony_ci .int_msk = BIT(2), 20062306a36Sopenharmony_ci .msg = "sec_ecc_2bit_err_rint" 20162306a36Sopenharmony_ci }, 20262306a36Sopenharmony_ci { 20362306a36Sopenharmony_ci .int_msk = BIT(3), 20462306a36Sopenharmony_ci .msg = "sec_ecc_1bit_err_rint" 20562306a36Sopenharmony_ci }, 20662306a36Sopenharmony_ci { 20762306a36Sopenharmony_ci .int_msk = BIT(4), 20862306a36Sopenharmony_ci .msg = "sec_req_trng_timeout_rint" 20962306a36Sopenharmony_ci }, 21062306a36Sopenharmony_ci { 21162306a36Sopenharmony_ci .int_msk = BIT(5), 21262306a36Sopenharmony_ci .msg = "sec_fsm_hbeat_rint" 21362306a36Sopenharmony_ci }, 21462306a36Sopenharmony_ci { 21562306a36Sopenharmony_ci .int_msk = BIT(6), 21662306a36Sopenharmony_ci .msg = "sec_channel_req_rng_timeout_rint" 21762306a36Sopenharmony_ci }, 21862306a36Sopenharmony_ci { 21962306a36Sopenharmony_ci .int_msk = BIT(7), 22062306a36Sopenharmony_ci .msg = "sec_bd_err_rint" 22162306a36Sopenharmony_ci }, 22262306a36Sopenharmony_ci { 22362306a36Sopenharmony_ci .int_msk = BIT(8), 22462306a36Sopenharmony_ci .msg = "sec_chain_buff_err_rint" 22562306a36Sopenharmony_ci }, 22662306a36Sopenharmony_ci { 22762306a36Sopenharmony_ci .int_msk = BIT(14), 22862306a36Sopenharmony_ci .msg = "sec_no_secure_access" 22962306a36Sopenharmony_ci }, 23062306a36Sopenharmony_ci { 23162306a36Sopenharmony_ci .int_msk = BIT(15), 23262306a36Sopenharmony_ci .msg = "sec_wrapping_key_auth_err" 23362306a36Sopenharmony_ci }, 23462306a36Sopenharmony_ci { 23562306a36Sopenharmony_ci .int_msk = BIT(16), 23662306a36Sopenharmony_ci .msg = "sec_km_key_crc_fail" 23762306a36Sopenharmony_ci }, 23862306a36Sopenharmony_ci { 23962306a36Sopenharmony_ci .int_msk = BIT(17), 24062306a36Sopenharmony_ci .msg = "sec_axi_poison_err" 24162306a36Sopenharmony_ci }, 24262306a36Sopenharmony_ci { 24362306a36Sopenharmony_ci .int_msk = BIT(18), 24462306a36Sopenharmony_ci .msg = "sec_sva_err" 24562306a36Sopenharmony_ci }, 24662306a36Sopenharmony_ci {} 24762306a36Sopenharmony_ci}; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic const char * const sec_dbg_file_name[] = { 25062306a36Sopenharmony_ci [SEC_CLEAR_ENABLE] = "clear_enable", 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic struct sec_dfx_item sec_dfx_labels[] = { 25462306a36Sopenharmony_ci {"send_cnt", offsetof(struct sec_dfx, send_cnt)}, 25562306a36Sopenharmony_ci {"recv_cnt", offsetof(struct sec_dfx, recv_cnt)}, 25662306a36Sopenharmony_ci {"send_busy_cnt", offsetof(struct sec_dfx, send_busy_cnt)}, 25762306a36Sopenharmony_ci {"recv_busy_cnt", offsetof(struct sec_dfx, recv_busy_cnt)}, 25862306a36Sopenharmony_ci {"err_bd_cnt", offsetof(struct sec_dfx, err_bd_cnt)}, 25962306a36Sopenharmony_ci {"invalid_req_cnt", offsetof(struct sec_dfx, invalid_req_cnt)}, 26062306a36Sopenharmony_ci {"done_flag_cnt", offsetof(struct sec_dfx, done_flag_cnt)}, 26162306a36Sopenharmony_ci}; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic const struct debugfs_reg32 sec_dfx_regs[] = { 26462306a36Sopenharmony_ci {"SEC_PF_ABNORMAL_INT_SOURCE ", 0x301010}, 26562306a36Sopenharmony_ci {"SEC_SAA_EN ", 0x301270}, 26662306a36Sopenharmony_ci {"SEC_BD_LATENCY_MIN ", 0x301600}, 26762306a36Sopenharmony_ci {"SEC_BD_LATENCY_MAX ", 0x301608}, 26862306a36Sopenharmony_ci {"SEC_BD_LATENCY_AVG ", 0x30160C}, 26962306a36Sopenharmony_ci {"SEC_BD_NUM_IN_SAA0 ", 0x301670}, 27062306a36Sopenharmony_ci {"SEC_BD_NUM_IN_SAA1 ", 0x301674}, 27162306a36Sopenharmony_ci {"SEC_BD_NUM_IN_SEC ", 0x301680}, 27262306a36Sopenharmony_ci {"SEC_ECC_1BIT_CNT ", 0x301C00}, 27362306a36Sopenharmony_ci {"SEC_ECC_1BIT_INFO ", 0x301C04}, 27462306a36Sopenharmony_ci {"SEC_ECC_2BIT_CNT ", 0x301C10}, 27562306a36Sopenharmony_ci {"SEC_ECC_2BIT_INFO ", 0x301C14}, 27662306a36Sopenharmony_ci {"SEC_BD_SAA0 ", 0x301C20}, 27762306a36Sopenharmony_ci {"SEC_BD_SAA1 ", 0x301C24}, 27862306a36Sopenharmony_ci {"SEC_BD_SAA2 ", 0x301C28}, 27962306a36Sopenharmony_ci {"SEC_BD_SAA3 ", 0x301C2C}, 28062306a36Sopenharmony_ci {"SEC_BD_SAA4 ", 0x301C30}, 28162306a36Sopenharmony_ci {"SEC_BD_SAA5 ", 0x301C34}, 28262306a36Sopenharmony_ci {"SEC_BD_SAA6 ", 0x301C38}, 28362306a36Sopenharmony_ci {"SEC_BD_SAA7 ", 0x301C3C}, 28462306a36Sopenharmony_ci {"SEC_BD_SAA8 ", 0x301C40}, 28562306a36Sopenharmony_ci}; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci/* define the SEC's dfx regs region and region length */ 28862306a36Sopenharmony_cistatic struct dfx_diff_registers sec_diff_regs[] = { 28962306a36Sopenharmony_ci { 29062306a36Sopenharmony_ci .reg_offset = SEC_DFX_BASE, 29162306a36Sopenharmony_ci .reg_len = SEC_DFX_BASE_LEN, 29262306a36Sopenharmony_ci }, { 29362306a36Sopenharmony_ci .reg_offset = SEC_DFX_COMMON1, 29462306a36Sopenharmony_ci .reg_len = SEC_DFX_COMMON1_LEN, 29562306a36Sopenharmony_ci }, { 29662306a36Sopenharmony_ci .reg_offset = SEC_DFX_COMMON2, 29762306a36Sopenharmony_ci .reg_len = SEC_DFX_COMMON2_LEN, 29862306a36Sopenharmony_ci }, { 29962306a36Sopenharmony_ci .reg_offset = SEC_DFX_CORE, 30062306a36Sopenharmony_ci .reg_len = SEC_DFX_CORE_LEN, 30162306a36Sopenharmony_ci }, 30262306a36Sopenharmony_ci}; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic int sec_diff_regs_show(struct seq_file *s, void *unused) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci struct hisi_qm *qm = s->private; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.acc_diff_regs, 30962306a36Sopenharmony_ci ARRAY_SIZE(sec_diff_regs)); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci return 0; 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(sec_diff_regs); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic bool pf_q_num_flag; 31662306a36Sopenharmony_cistatic int sec_pf_q_num_set(const char *val, const struct kernel_param *kp) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci pf_q_num_flag = true; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_SEC_PF); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic const struct kernel_param_ops sec_pf_q_num_ops = { 32462306a36Sopenharmony_ci .set = sec_pf_q_num_set, 32562306a36Sopenharmony_ci .get = param_get_int, 32662306a36Sopenharmony_ci}; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistatic u32 pf_q_num = SEC_PF_DEF_Q_NUM; 32962306a36Sopenharmony_cimodule_param_cb(pf_q_num, &sec_pf_q_num_ops, &pf_q_num, 0444); 33062306a36Sopenharmony_ciMODULE_PARM_DESC(pf_q_num, "Number of queues in PF(v1 2-4096, v2 2-1024)"); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic int sec_ctx_q_num_set(const char *val, const struct kernel_param *kp) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci u32 ctx_q_num; 33562306a36Sopenharmony_ci int ret; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (!val) 33862306a36Sopenharmony_ci return -EINVAL; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci ret = kstrtou32(val, 10, &ctx_q_num); 34162306a36Sopenharmony_ci if (ret) 34262306a36Sopenharmony_ci return -EINVAL; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (!ctx_q_num || ctx_q_num > SEC_CTX_Q_NUM_MAX || ctx_q_num & 0x1) { 34562306a36Sopenharmony_ci pr_err("ctx queue num[%u] is invalid!\n", ctx_q_num); 34662306a36Sopenharmony_ci return -EINVAL; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci return param_set_int(val, kp); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic const struct kernel_param_ops sec_ctx_q_num_ops = { 35362306a36Sopenharmony_ci .set = sec_ctx_q_num_set, 35462306a36Sopenharmony_ci .get = param_get_int, 35562306a36Sopenharmony_ci}; 35662306a36Sopenharmony_cistatic u32 ctx_q_num = SEC_CTX_Q_NUM_DEF; 35762306a36Sopenharmony_cimodule_param_cb(ctx_q_num, &sec_ctx_q_num_ops, &ctx_q_num, 0444); 35862306a36Sopenharmony_ciMODULE_PARM_DESC(ctx_q_num, "Queue num in ctx (2 default, 2, 4, ..., 32)"); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic const struct kernel_param_ops vfs_num_ops = { 36162306a36Sopenharmony_ci .set = vfs_num_set, 36262306a36Sopenharmony_ci .get = param_get_int, 36362306a36Sopenharmony_ci}; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic u32 vfs_num; 36662306a36Sopenharmony_cimodule_param_cb(vfs_num, &vfs_num_ops, &vfs_num, 0444); 36762306a36Sopenharmony_ciMODULE_PARM_DESC(vfs_num, "Number of VFs to enable(1-63), 0(default)"); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_civoid sec_destroy_qps(struct hisi_qp **qps, int qp_num) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci hisi_qm_free_qps(qps, qp_num); 37262306a36Sopenharmony_ci kfree(qps); 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistruct hisi_qp **sec_create_qps(void) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci int node = cpu_to_node(smp_processor_id()); 37862306a36Sopenharmony_ci u32 ctx_num = ctx_q_num; 37962306a36Sopenharmony_ci struct hisi_qp **qps; 38062306a36Sopenharmony_ci int ret; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci qps = kcalloc(ctx_num, sizeof(struct hisi_qp *), GFP_KERNEL); 38362306a36Sopenharmony_ci if (!qps) 38462306a36Sopenharmony_ci return NULL; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci ret = hisi_qm_alloc_qps_node(&sec_devices, ctx_num, 0, node, qps); 38762306a36Sopenharmony_ci if (!ret) 38862306a36Sopenharmony_ci return qps; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci kfree(qps); 39162306a36Sopenharmony_ci return NULL; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ciu64 sec_get_alg_bitmap(struct hisi_qm *qm, u32 high, u32 low) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci u32 cap_val_h, cap_val_l; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci cap_val_h = qm->cap_tables.dev_cap_table[high].cap_val; 39962306a36Sopenharmony_ci cap_val_l = qm->cap_tables.dev_cap_table[low].cap_val; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return ((u64)cap_val_h << SEC_ALG_BITMAP_SHIFT) | (u64)cap_val_l; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_cistatic const struct kernel_param_ops sec_uacce_mode_ops = { 40562306a36Sopenharmony_ci .set = uacce_mode_set, 40662306a36Sopenharmony_ci .get = param_get_int, 40762306a36Sopenharmony_ci}; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci/* 41062306a36Sopenharmony_ci * uacce_mode = 0 means sec only register to crypto, 41162306a36Sopenharmony_ci * uacce_mode = 1 means sec both register to crypto and uacce. 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_cistatic u32 uacce_mode = UACCE_MODE_NOUACCE; 41462306a36Sopenharmony_cimodule_param_cb(uacce_mode, &sec_uacce_mode_ops, &uacce_mode, 0444); 41562306a36Sopenharmony_ciMODULE_PARM_DESC(uacce_mode, UACCE_MODE_DESC); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic const struct pci_device_id sec_dev_ids[] = { 41862306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HUAWEI_SEC_PF) }, 41962306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HUAWEI_SEC_VF) }, 42062306a36Sopenharmony_ci { 0, } 42162306a36Sopenharmony_ci}; 42262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, sec_dev_ids); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_cistatic void sec_set_endian(struct hisi_qm *qm) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci u32 reg; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci reg = readl_relaxed(qm->io_base + SEC_CONTROL_REG); 42962306a36Sopenharmony_ci reg &= ~(BIT(1) | BIT(0)); 43062306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_64BIT)) 43162306a36Sopenharmony_ci reg |= BIT(1); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN)) 43462306a36Sopenharmony_ci reg |= BIT(0); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci writel_relaxed(reg, qm->io_base + SEC_CONTROL_REG); 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic void sec_engine_sva_config(struct hisi_qm *qm) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci u32 reg; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (qm->ver > QM_HW_V2) { 44462306a36Sopenharmony_ci reg = readl_relaxed(qm->io_base + 44562306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL0_REG_V3); 44662306a36Sopenharmony_ci reg |= SEC_USER0_SMMU_NORMAL; 44762306a36Sopenharmony_ci writel_relaxed(reg, qm->io_base + 44862306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL0_REG_V3); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci reg = readl_relaxed(qm->io_base + 45162306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL1_REG_V3); 45262306a36Sopenharmony_ci reg &= SEC_USER1_SMMU_MASK_V3; 45362306a36Sopenharmony_ci reg |= SEC_USER1_SMMU_NORMAL_V3; 45462306a36Sopenharmony_ci writel_relaxed(reg, qm->io_base + 45562306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL1_REG_V3); 45662306a36Sopenharmony_ci } else { 45762306a36Sopenharmony_ci reg = readl_relaxed(qm->io_base + 45862306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL0_REG); 45962306a36Sopenharmony_ci reg |= SEC_USER0_SMMU_NORMAL; 46062306a36Sopenharmony_ci writel_relaxed(reg, qm->io_base + 46162306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL0_REG); 46262306a36Sopenharmony_ci reg = readl_relaxed(qm->io_base + 46362306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL1_REG); 46462306a36Sopenharmony_ci reg &= SEC_USER1_SMMU_MASK; 46562306a36Sopenharmony_ci if (qm->use_sva) 46662306a36Sopenharmony_ci reg |= SEC_USER1_SMMU_SVA; 46762306a36Sopenharmony_ci else 46862306a36Sopenharmony_ci reg |= SEC_USER1_SMMU_NORMAL; 46962306a36Sopenharmony_ci writel_relaxed(reg, qm->io_base + 47062306a36Sopenharmony_ci SEC_INTERFACE_USER_CTRL1_REG); 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic void sec_open_sva_prefetch(struct hisi_qm *qm) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci u32 val; 47762306a36Sopenharmony_ci int ret; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (!test_bit(QM_SUPPORT_SVA_PREFETCH, &qm->caps)) 48062306a36Sopenharmony_ci return; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* Enable prefetch */ 48362306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + SEC_PREFETCH_CFG); 48462306a36Sopenharmony_ci val &= SEC_PREFETCH_ENABLE; 48562306a36Sopenharmony_ci writel(val, qm->io_base + SEC_PREFETCH_CFG); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci ret = readl_relaxed_poll_timeout(qm->io_base + SEC_PREFETCH_CFG, 48862306a36Sopenharmony_ci val, !(val & SEC_PREFETCH_DISABLE), 48962306a36Sopenharmony_ci SEC_DELAY_10_US, SEC_POLL_TIMEOUT_US); 49062306a36Sopenharmony_ci if (ret) 49162306a36Sopenharmony_ci pci_err(qm->pdev, "failed to open sva prefetch\n"); 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_cistatic void sec_close_sva_prefetch(struct hisi_qm *qm) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci u32 val; 49762306a36Sopenharmony_ci int ret; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (!test_bit(QM_SUPPORT_SVA_PREFETCH, &qm->caps)) 50062306a36Sopenharmony_ci return; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + SEC_PREFETCH_CFG); 50362306a36Sopenharmony_ci val |= SEC_PREFETCH_DISABLE; 50462306a36Sopenharmony_ci writel(val, qm->io_base + SEC_PREFETCH_CFG); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci ret = readl_relaxed_poll_timeout(qm->io_base + SEC_SVA_TRANS, 50762306a36Sopenharmony_ci val, !(val & SEC_SVA_DISABLE_READY), 50862306a36Sopenharmony_ci SEC_DELAY_10_US, SEC_POLL_TIMEOUT_US); 50962306a36Sopenharmony_ci if (ret) 51062306a36Sopenharmony_ci pci_err(qm->pdev, "failed to close sva prefetch\n"); 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic void sec_enable_clock_gate(struct hisi_qm *qm) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci u32 val; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci if (qm->ver < QM_HW_V3) 51862306a36Sopenharmony_ci return; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + SEC_CONTROL_REG); 52162306a36Sopenharmony_ci val |= SEC_CLK_GATE_ENABLE; 52262306a36Sopenharmony_ci writel_relaxed(val, qm->io_base + SEC_CONTROL_REG); 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci val = readl(qm->io_base + SEC_DYNAMIC_GATE_REG); 52562306a36Sopenharmony_ci val |= SEC_DYNAMIC_GATE_EN; 52662306a36Sopenharmony_ci writel(val, qm->io_base + SEC_DYNAMIC_GATE_REG); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci val = readl(qm->io_base + SEC_CORE_AUTO_GATE); 52962306a36Sopenharmony_ci val |= SEC_CORE_AUTO_GATE_EN; 53062306a36Sopenharmony_ci writel(val, qm->io_base + SEC_CORE_AUTO_GATE); 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic void sec_disable_clock_gate(struct hisi_qm *qm) 53462306a36Sopenharmony_ci{ 53562306a36Sopenharmony_ci u32 val; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* Kunpeng920 needs to close clock gating */ 53862306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + SEC_CONTROL_REG); 53962306a36Sopenharmony_ci val &= SEC_CLK_GATE_DISABLE; 54062306a36Sopenharmony_ci writel_relaxed(val, qm->io_base + SEC_CONTROL_REG); 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic int sec_engine_init(struct hisi_qm *qm) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci int ret; 54662306a36Sopenharmony_ci u32 reg; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* disable clock gate control before mem init */ 54962306a36Sopenharmony_ci sec_disable_clock_gate(qm); 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci writel_relaxed(0x1, qm->io_base + SEC_MEM_START_INIT_REG); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci ret = readl_relaxed_poll_timeout(qm->io_base + SEC_MEM_INIT_DONE_REG, 55462306a36Sopenharmony_ci reg, reg & 0x1, SEC_DELAY_10_US, 55562306a36Sopenharmony_ci SEC_POLL_TIMEOUT_US); 55662306a36Sopenharmony_ci if (ret) { 55762306a36Sopenharmony_ci pci_err(qm->pdev, "fail to init sec mem\n"); 55862306a36Sopenharmony_ci return ret; 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci reg = readl_relaxed(qm->io_base + SEC_CONTROL_REG); 56262306a36Sopenharmony_ci reg |= (0x1 << SEC_TRNG_EN_SHIFT); 56362306a36Sopenharmony_ci writel_relaxed(reg, qm->io_base + SEC_CONTROL_REG); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci sec_engine_sva_config(qm); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci writel(SEC_SINGLE_PORT_MAX_TRANS, 56862306a36Sopenharmony_ci qm->io_base + AM_CFG_SINGLE_PORT_MAX_TRANS); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci reg = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_CORE_ENABLE_BITMAP, qm->cap_ver); 57162306a36Sopenharmony_ci writel(reg, qm->io_base + SEC_SAA_EN_REG); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (qm->ver < QM_HW_V3) { 57462306a36Sopenharmony_ci /* HW V2 enable sm4 extra mode, as ctr/ecb */ 57562306a36Sopenharmony_ci writel_relaxed(SEC_BD_ERR_CHK_EN0, 57662306a36Sopenharmony_ci qm->io_base + SEC_BD_ERR_CHK_EN_REG0); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* HW V2 enable sm4 xts mode multiple iv */ 57962306a36Sopenharmony_ci writel_relaxed(SEC_BD_ERR_CHK_EN1, 58062306a36Sopenharmony_ci qm->io_base + SEC_BD_ERR_CHK_EN_REG1); 58162306a36Sopenharmony_ci writel_relaxed(SEC_BD_ERR_CHK_EN3, 58262306a36Sopenharmony_ci qm->io_base + SEC_BD_ERR_CHK_EN_REG3); 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci /* config endian */ 58662306a36Sopenharmony_ci sec_set_endian(qm); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci sec_enable_clock_gate(qm); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci return 0; 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic int sec_set_user_domain_and_cache(struct hisi_qm *qm) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci /* qm user domain */ 59662306a36Sopenharmony_ci writel(AXUSER_BASE, qm->io_base + QM_ARUSER_M_CFG_1); 59762306a36Sopenharmony_ci writel(ARUSER_M_CFG_ENABLE, qm->io_base + QM_ARUSER_M_CFG_ENABLE); 59862306a36Sopenharmony_ci writel(AXUSER_BASE, qm->io_base + QM_AWUSER_M_CFG_1); 59962306a36Sopenharmony_ci writel(AWUSER_M_CFG_ENABLE, qm->io_base + QM_AWUSER_M_CFG_ENABLE); 60062306a36Sopenharmony_ci writel(WUSER_M_CFG_ENABLE, qm->io_base + QM_WUSER_M_CFG_ENABLE); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* qm cache */ 60362306a36Sopenharmony_ci writel(AXI_M_CFG, qm->io_base + QM_AXI_M_CFG); 60462306a36Sopenharmony_ci writel(AXI_M_CFG_ENABLE, qm->io_base + QM_AXI_M_CFG_ENABLE); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* disable FLR triggered by BME(bus master enable) */ 60762306a36Sopenharmony_ci writel(PEH_AXUSER_CFG, qm->io_base + QM_PEH_AXUSER_CFG); 60862306a36Sopenharmony_ci writel(PEH_AXUSER_CFG_ENABLE, qm->io_base + QM_PEH_AXUSER_CFG_ENABLE); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* enable sqc,cqc writeback */ 61162306a36Sopenharmony_ci writel(SQC_CACHE_ENABLE | CQC_CACHE_ENABLE | SQC_CACHE_WB_ENABLE | 61262306a36Sopenharmony_ci CQC_CACHE_WB_ENABLE | FIELD_PREP(SQC_CACHE_WB_THRD, 1) | 61362306a36Sopenharmony_ci FIELD_PREP(CQC_CACHE_WB_THRD, 1), qm->io_base + QM_CACHE_CTL); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci return sec_engine_init(qm); 61662306a36Sopenharmony_ci} 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci/* sec_debug_regs_clear() - clear the sec debug regs */ 61962306a36Sopenharmony_cistatic void sec_debug_regs_clear(struct hisi_qm *qm) 62062306a36Sopenharmony_ci{ 62162306a36Sopenharmony_ci int i; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* clear sec dfx regs */ 62462306a36Sopenharmony_ci writel(0x1, qm->io_base + SEC_CTRL_CNT_CLR_CE); 62562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sec_dfx_regs); i++) 62662306a36Sopenharmony_ci readl(qm->io_base + sec_dfx_regs[i].offset); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci /* clear rdclr_en */ 62962306a36Sopenharmony_ci writel(0x0, qm->io_base + SEC_CTRL_CNT_CLR_CE); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci hisi_qm_debug_regs_clear(qm); 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_cistatic void sec_master_ooo_ctrl(struct hisi_qm *qm, bool enable) 63562306a36Sopenharmony_ci{ 63662306a36Sopenharmony_ci u32 val1, val2; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci val1 = readl(qm->io_base + SEC_CONTROL_REG); 63962306a36Sopenharmony_ci if (enable) { 64062306a36Sopenharmony_ci val1 |= SEC_AXI_SHUTDOWN_ENABLE; 64162306a36Sopenharmony_ci val2 = hisi_qm_get_hw_info(qm, sec_basic_info, 64262306a36Sopenharmony_ci SEC_OOO_SHUTDOWN_MASK_CAP, qm->cap_ver); 64362306a36Sopenharmony_ci } else { 64462306a36Sopenharmony_ci val1 &= SEC_AXI_SHUTDOWN_DISABLE; 64562306a36Sopenharmony_ci val2 = 0x0; 64662306a36Sopenharmony_ci } 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci if (qm->ver > QM_HW_V2) 64962306a36Sopenharmony_ci writel(val2, qm->io_base + SEC_OOO_SHUTDOWN_SEL); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci writel(val1, qm->io_base + SEC_CONTROL_REG); 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic void sec_hw_error_enable(struct hisi_qm *qm) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci u32 ce, nfe; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci if (qm->ver == QM_HW_V1) { 65962306a36Sopenharmony_ci writel(SEC_CORE_INT_DISABLE, qm->io_base + SEC_CORE_INT_MASK); 66062306a36Sopenharmony_ci pci_info(qm->pdev, "V1 not support hw error handle\n"); 66162306a36Sopenharmony_ci return; 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci ce = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_CE_MASK_CAP, qm->cap_ver); 66562306a36Sopenharmony_ci nfe = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci /* clear SEC hw error source if having */ 66862306a36Sopenharmony_ci writel(ce | nfe | SEC_RAS_FE_ENB_MSK, qm->io_base + SEC_CORE_INT_SOURCE); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* enable RAS int */ 67162306a36Sopenharmony_ci writel(ce, qm->io_base + SEC_RAS_CE_REG); 67262306a36Sopenharmony_ci writel(SEC_RAS_FE_ENB_MSK, qm->io_base + SEC_RAS_FE_REG); 67362306a36Sopenharmony_ci writel(nfe, qm->io_base + SEC_RAS_NFE_REG); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* enable SEC block master OOO when nfe occurs on Kunpeng930 */ 67662306a36Sopenharmony_ci sec_master_ooo_ctrl(qm, true); 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci /* enable SEC hw error interrupts */ 67962306a36Sopenharmony_ci writel(ce | nfe | SEC_RAS_FE_ENB_MSK, qm->io_base + SEC_CORE_INT_MASK); 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic void sec_hw_error_disable(struct hisi_qm *qm) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci /* disable SEC hw error interrupts */ 68562306a36Sopenharmony_ci writel(SEC_CORE_INT_DISABLE, qm->io_base + SEC_CORE_INT_MASK); 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci /* disable SEC block master OOO when nfe occurs on Kunpeng930 */ 68862306a36Sopenharmony_ci sec_master_ooo_ctrl(qm, false); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* disable RAS int */ 69162306a36Sopenharmony_ci writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_CE_REG); 69262306a36Sopenharmony_ci writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_FE_REG); 69362306a36Sopenharmony_ci writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_NFE_REG); 69462306a36Sopenharmony_ci} 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_cistatic u32 sec_clear_enable_read(struct hisi_qm *qm) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci return readl(qm->io_base + SEC_CTRL_CNT_CLR_CE) & 69962306a36Sopenharmony_ci SEC_CTRL_CNT_CLR_CE_BIT; 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic int sec_clear_enable_write(struct hisi_qm *qm, u32 val) 70362306a36Sopenharmony_ci{ 70462306a36Sopenharmony_ci u32 tmp; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci if (val != 1 && val) 70762306a36Sopenharmony_ci return -EINVAL; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci tmp = (readl(qm->io_base + SEC_CTRL_CNT_CLR_CE) & 71062306a36Sopenharmony_ci ~SEC_CTRL_CNT_CLR_CE_BIT) | val; 71162306a36Sopenharmony_ci writel(tmp, qm->io_base + SEC_CTRL_CNT_CLR_CE); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci return 0; 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic ssize_t sec_debug_read(struct file *filp, char __user *buf, 71762306a36Sopenharmony_ci size_t count, loff_t *pos) 71862306a36Sopenharmony_ci{ 71962306a36Sopenharmony_ci struct sec_debug_file *file = filp->private_data; 72062306a36Sopenharmony_ci char tbuf[SEC_DBGFS_VAL_MAX_LEN]; 72162306a36Sopenharmony_ci struct hisi_qm *qm = file->qm; 72262306a36Sopenharmony_ci u32 val; 72362306a36Sopenharmony_ci int ret; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci ret = hisi_qm_get_dfx_access(qm); 72662306a36Sopenharmony_ci if (ret) 72762306a36Sopenharmony_ci return ret; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci spin_lock_irq(&file->lock); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci switch (file->index) { 73262306a36Sopenharmony_ci case SEC_CLEAR_ENABLE: 73362306a36Sopenharmony_ci val = sec_clear_enable_read(qm); 73462306a36Sopenharmony_ci break; 73562306a36Sopenharmony_ci default: 73662306a36Sopenharmony_ci goto err_input; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci spin_unlock_irq(&file->lock); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci hisi_qm_put_dfx_access(qm); 74262306a36Sopenharmony_ci ret = snprintf(tbuf, SEC_DBGFS_VAL_MAX_LEN, "%u\n", val); 74362306a36Sopenharmony_ci return simple_read_from_buffer(buf, count, pos, tbuf, ret); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cierr_input: 74662306a36Sopenharmony_ci spin_unlock_irq(&file->lock); 74762306a36Sopenharmony_ci hisi_qm_put_dfx_access(qm); 74862306a36Sopenharmony_ci return -EINVAL; 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_cistatic ssize_t sec_debug_write(struct file *filp, const char __user *buf, 75262306a36Sopenharmony_ci size_t count, loff_t *pos) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci struct sec_debug_file *file = filp->private_data; 75562306a36Sopenharmony_ci char tbuf[SEC_DBGFS_VAL_MAX_LEN]; 75662306a36Sopenharmony_ci struct hisi_qm *qm = file->qm; 75762306a36Sopenharmony_ci unsigned long val; 75862306a36Sopenharmony_ci int len, ret; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci if (*pos != 0) 76162306a36Sopenharmony_ci return 0; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci if (count >= SEC_DBGFS_VAL_MAX_LEN) 76462306a36Sopenharmony_ci return -ENOSPC; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci len = simple_write_to_buffer(tbuf, SEC_DBGFS_VAL_MAX_LEN - 1, 76762306a36Sopenharmony_ci pos, buf, count); 76862306a36Sopenharmony_ci if (len < 0) 76962306a36Sopenharmony_ci return len; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci tbuf[len] = '\0'; 77262306a36Sopenharmony_ci if (kstrtoul(tbuf, 0, &val)) 77362306a36Sopenharmony_ci return -EFAULT; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci ret = hisi_qm_get_dfx_access(qm); 77662306a36Sopenharmony_ci if (ret) 77762306a36Sopenharmony_ci return ret; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci spin_lock_irq(&file->lock); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci switch (file->index) { 78262306a36Sopenharmony_ci case SEC_CLEAR_ENABLE: 78362306a36Sopenharmony_ci ret = sec_clear_enable_write(qm, val); 78462306a36Sopenharmony_ci if (ret) 78562306a36Sopenharmony_ci goto err_input; 78662306a36Sopenharmony_ci break; 78762306a36Sopenharmony_ci default: 78862306a36Sopenharmony_ci ret = -EINVAL; 78962306a36Sopenharmony_ci goto err_input; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci ret = count; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci err_input: 79562306a36Sopenharmony_ci spin_unlock_irq(&file->lock); 79662306a36Sopenharmony_ci hisi_qm_put_dfx_access(qm); 79762306a36Sopenharmony_ci return ret; 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_cistatic const struct file_operations sec_dbg_fops = { 80162306a36Sopenharmony_ci .owner = THIS_MODULE, 80262306a36Sopenharmony_ci .open = simple_open, 80362306a36Sopenharmony_ci .read = sec_debug_read, 80462306a36Sopenharmony_ci .write = sec_debug_write, 80562306a36Sopenharmony_ci}; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_cistatic int sec_debugfs_atomic64_get(void *data, u64 *val) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci *val = atomic64_read((atomic64_t *)data); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci return 0; 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cistatic int sec_debugfs_atomic64_set(void *data, u64 val) 81562306a36Sopenharmony_ci{ 81662306a36Sopenharmony_ci if (val) 81762306a36Sopenharmony_ci return -EINVAL; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci atomic64_set((atomic64_t *)data, 0); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci return 0; 82262306a36Sopenharmony_ci} 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(sec_atomic64_ops, sec_debugfs_atomic64_get, 82562306a36Sopenharmony_ci sec_debugfs_atomic64_set, "%lld\n"); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_cistatic int sec_regs_show(struct seq_file *s, void *unused) 82862306a36Sopenharmony_ci{ 82962306a36Sopenharmony_ci hisi_qm_regs_dump(s, s->private); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci return 0; 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(sec_regs); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_cistatic int sec_core_debug_init(struct hisi_qm *qm) 83762306a36Sopenharmony_ci{ 83862306a36Sopenharmony_ci struct dfx_diff_registers *sec_regs = qm->debug.acc_diff_regs; 83962306a36Sopenharmony_ci struct sec_dev *sec = container_of(qm, struct sec_dev, qm); 84062306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 84162306a36Sopenharmony_ci struct sec_dfx *dfx = &sec->debug.dfx; 84262306a36Sopenharmony_ci struct debugfs_regset32 *regset; 84362306a36Sopenharmony_ci struct dentry *tmp_d; 84462306a36Sopenharmony_ci int i; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci tmp_d = debugfs_create_dir("sec_dfx", qm->debug.debug_root); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); 84962306a36Sopenharmony_ci if (!regset) 85062306a36Sopenharmony_ci return -ENOMEM; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci regset->regs = sec_dfx_regs; 85362306a36Sopenharmony_ci regset->nregs = ARRAY_SIZE(sec_dfx_regs); 85462306a36Sopenharmony_ci regset->base = qm->io_base; 85562306a36Sopenharmony_ci regset->dev = dev; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci if (qm->pdev->device == PCI_DEVICE_ID_HUAWEI_SEC_PF) 85862306a36Sopenharmony_ci debugfs_create_file("regs", 0444, tmp_d, regset, &sec_regs_fops); 85962306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF && sec_regs) 86062306a36Sopenharmony_ci debugfs_create_file("diff_regs", 0444, tmp_d, 86162306a36Sopenharmony_ci qm, &sec_diff_regs_fops); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sec_dfx_labels); i++) { 86462306a36Sopenharmony_ci atomic64_t *data = (atomic64_t *)((uintptr_t)dfx + 86562306a36Sopenharmony_ci sec_dfx_labels[i].offset); 86662306a36Sopenharmony_ci debugfs_create_file(sec_dfx_labels[i].name, 0644, 86762306a36Sopenharmony_ci tmp_d, data, &sec_atomic64_ops); 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci return 0; 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic int sec_debug_init(struct hisi_qm *qm) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci struct sec_dev *sec = container_of(qm, struct sec_dev, qm); 87662306a36Sopenharmony_ci int i; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci if (qm->pdev->device == PCI_DEVICE_ID_HUAWEI_SEC_PF) { 87962306a36Sopenharmony_ci for (i = SEC_CLEAR_ENABLE; i < SEC_DEBUG_FILE_NUM; i++) { 88062306a36Sopenharmony_ci spin_lock_init(&sec->debug.files[i].lock); 88162306a36Sopenharmony_ci sec->debug.files[i].index = i; 88262306a36Sopenharmony_ci sec->debug.files[i].qm = qm; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci debugfs_create_file(sec_dbg_file_name[i], 0600, 88562306a36Sopenharmony_ci qm->debug.debug_root, 88662306a36Sopenharmony_ci sec->debug.files + i, 88762306a36Sopenharmony_ci &sec_dbg_fops); 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci } 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci return sec_core_debug_init(qm); 89262306a36Sopenharmony_ci} 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_cistatic int sec_debugfs_init(struct hisi_qm *qm) 89562306a36Sopenharmony_ci{ 89662306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 89762306a36Sopenharmony_ci int ret; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci qm->debug.debug_root = debugfs_create_dir(dev_name(dev), 90062306a36Sopenharmony_ci sec_debugfs_root); 90162306a36Sopenharmony_ci qm->debug.sqe_mask_offset = SEC_SQE_MASK_OFFSET; 90262306a36Sopenharmony_ci qm->debug.sqe_mask_len = SEC_SQE_MASK_LEN; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci ret = hisi_qm_regs_debugfs_init(qm, sec_diff_regs, ARRAY_SIZE(sec_diff_regs)); 90562306a36Sopenharmony_ci if (ret) { 90662306a36Sopenharmony_ci dev_warn(dev, "Failed to init SEC diff regs!\n"); 90762306a36Sopenharmony_ci goto debugfs_remove; 90862306a36Sopenharmony_ci } 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci hisi_qm_debug_init(qm); 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci ret = sec_debug_init(qm); 91362306a36Sopenharmony_ci if (ret) 91462306a36Sopenharmony_ci goto failed_to_create; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci return 0; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_cifailed_to_create: 91962306a36Sopenharmony_ci hisi_qm_regs_debugfs_uninit(qm, ARRAY_SIZE(sec_diff_regs)); 92062306a36Sopenharmony_cidebugfs_remove: 92162306a36Sopenharmony_ci debugfs_remove_recursive(sec_debugfs_root); 92262306a36Sopenharmony_ci return ret; 92362306a36Sopenharmony_ci} 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cistatic void sec_debugfs_exit(struct hisi_qm *qm) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci hisi_qm_regs_debugfs_uninit(qm, ARRAY_SIZE(sec_diff_regs)); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci debugfs_remove_recursive(qm->debug.debug_root); 93062306a36Sopenharmony_ci} 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_cistatic int sec_show_last_regs_init(struct hisi_qm *qm) 93362306a36Sopenharmony_ci{ 93462306a36Sopenharmony_ci struct qm_debug *debug = &qm->debug; 93562306a36Sopenharmony_ci int i; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci debug->last_words = kcalloc(ARRAY_SIZE(sec_dfx_regs), 93862306a36Sopenharmony_ci sizeof(unsigned int), GFP_KERNEL); 93962306a36Sopenharmony_ci if (!debug->last_words) 94062306a36Sopenharmony_ci return -ENOMEM; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sec_dfx_regs); i++) 94362306a36Sopenharmony_ci debug->last_words[i] = readl_relaxed(qm->io_base + 94462306a36Sopenharmony_ci sec_dfx_regs[i].offset); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci return 0; 94762306a36Sopenharmony_ci} 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_cistatic void sec_show_last_regs_uninit(struct hisi_qm *qm) 95062306a36Sopenharmony_ci{ 95162306a36Sopenharmony_ci struct qm_debug *debug = &qm->debug; 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci if (qm->fun_type == QM_HW_VF || !debug->last_words) 95462306a36Sopenharmony_ci return; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci kfree(debug->last_words); 95762306a36Sopenharmony_ci debug->last_words = NULL; 95862306a36Sopenharmony_ci} 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_cistatic void sec_show_last_dfx_regs(struct hisi_qm *qm) 96162306a36Sopenharmony_ci{ 96262306a36Sopenharmony_ci struct qm_debug *debug = &qm->debug; 96362306a36Sopenharmony_ci struct pci_dev *pdev = qm->pdev; 96462306a36Sopenharmony_ci u32 val; 96562306a36Sopenharmony_ci int i; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci if (qm->fun_type == QM_HW_VF || !debug->last_words) 96862306a36Sopenharmony_ci return; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci /* dumps last word of the debugging registers during controller reset */ 97162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sec_dfx_regs); i++) { 97262306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + sec_dfx_regs[i].offset); 97362306a36Sopenharmony_ci if (val != debug->last_words[i]) 97462306a36Sopenharmony_ci pci_info(pdev, "%s \t= 0x%08x => 0x%08x\n", 97562306a36Sopenharmony_ci sec_dfx_regs[i].name, debug->last_words[i], val); 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci} 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_cistatic void sec_log_hw_error(struct hisi_qm *qm, u32 err_sts) 98062306a36Sopenharmony_ci{ 98162306a36Sopenharmony_ci const struct sec_hw_error *errs = sec_hw_errors; 98262306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 98362306a36Sopenharmony_ci u32 err_val; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci while (errs->msg) { 98662306a36Sopenharmony_ci if (errs->int_msk & err_sts) { 98762306a36Sopenharmony_ci dev_err(dev, "%s [error status=0x%x] found\n", 98862306a36Sopenharmony_ci errs->msg, errs->int_msk); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci if (SEC_CORE_INT_STATUS_M_ECC & errs->int_msk) { 99162306a36Sopenharmony_ci err_val = readl(qm->io_base + 99262306a36Sopenharmony_ci SEC_CORE_SRAM_ECC_ERR_INFO); 99362306a36Sopenharmony_ci dev_err(dev, "multi ecc sram num=0x%x\n", 99462306a36Sopenharmony_ci ((err_val) >> SEC_ECC_NUM) & 99562306a36Sopenharmony_ci SEC_ECC_MASH); 99662306a36Sopenharmony_ci } 99762306a36Sopenharmony_ci } 99862306a36Sopenharmony_ci errs++; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci} 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_cistatic u32 sec_get_hw_err_status(struct hisi_qm *qm) 100362306a36Sopenharmony_ci{ 100462306a36Sopenharmony_ci return readl(qm->io_base + SEC_CORE_INT_STATUS); 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_cistatic void sec_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) 100862306a36Sopenharmony_ci{ 100962306a36Sopenharmony_ci u32 nfe; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci writel(err_sts, qm->io_base + SEC_CORE_INT_SOURCE); 101262306a36Sopenharmony_ci nfe = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver); 101362306a36Sopenharmony_ci writel(nfe, qm->io_base + SEC_RAS_NFE_REG); 101462306a36Sopenharmony_ci} 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_cistatic void sec_open_axi_master_ooo(struct hisi_qm *qm) 101762306a36Sopenharmony_ci{ 101862306a36Sopenharmony_ci u32 val; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci val = readl(qm->io_base + SEC_CONTROL_REG); 102162306a36Sopenharmony_ci writel(val & SEC_AXI_SHUTDOWN_DISABLE, qm->io_base + SEC_CONTROL_REG); 102262306a36Sopenharmony_ci writel(val | SEC_AXI_SHUTDOWN_ENABLE, qm->io_base + SEC_CONTROL_REG); 102362306a36Sopenharmony_ci} 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_cistatic void sec_err_info_init(struct hisi_qm *qm) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci struct hisi_qm_err_info *err_info = &qm->err_info; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci err_info->fe = SEC_RAS_FE_ENB_MSK; 103062306a36Sopenharmony_ci err_info->ce = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_QM_CE_MASK_CAP, qm->cap_ver); 103162306a36Sopenharmony_ci err_info->nfe = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_QM_NFE_MASK_CAP, qm->cap_ver); 103262306a36Sopenharmony_ci err_info->ecc_2bits_mask = SEC_CORE_INT_STATUS_M_ECC; 103362306a36Sopenharmony_ci err_info->qm_shutdown_mask = hisi_qm_get_hw_info(qm, sec_basic_info, 103462306a36Sopenharmony_ci SEC_QM_OOO_SHUTDOWN_MASK_CAP, qm->cap_ver); 103562306a36Sopenharmony_ci err_info->dev_shutdown_mask = hisi_qm_get_hw_info(qm, sec_basic_info, 103662306a36Sopenharmony_ci SEC_OOO_SHUTDOWN_MASK_CAP, qm->cap_ver); 103762306a36Sopenharmony_ci err_info->qm_reset_mask = hisi_qm_get_hw_info(qm, sec_basic_info, 103862306a36Sopenharmony_ci SEC_QM_RESET_MASK_CAP, qm->cap_ver); 103962306a36Sopenharmony_ci err_info->dev_reset_mask = hisi_qm_get_hw_info(qm, sec_basic_info, 104062306a36Sopenharmony_ci SEC_RESET_MASK_CAP, qm->cap_ver); 104162306a36Sopenharmony_ci err_info->msi_wr_port = BIT(0); 104262306a36Sopenharmony_ci err_info->acpi_rst = "SRST"; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic const struct hisi_qm_err_ini sec_err_ini = { 104662306a36Sopenharmony_ci .hw_init = sec_set_user_domain_and_cache, 104762306a36Sopenharmony_ci .hw_err_enable = sec_hw_error_enable, 104862306a36Sopenharmony_ci .hw_err_disable = sec_hw_error_disable, 104962306a36Sopenharmony_ci .get_dev_hw_err_status = sec_get_hw_err_status, 105062306a36Sopenharmony_ci .clear_dev_hw_err_status = sec_clear_hw_err_status, 105162306a36Sopenharmony_ci .log_dev_hw_err = sec_log_hw_error, 105262306a36Sopenharmony_ci .open_axi_master_ooo = sec_open_axi_master_ooo, 105362306a36Sopenharmony_ci .open_sva_prefetch = sec_open_sva_prefetch, 105462306a36Sopenharmony_ci .close_sva_prefetch = sec_close_sva_prefetch, 105562306a36Sopenharmony_ci .show_last_dfx_regs = sec_show_last_dfx_regs, 105662306a36Sopenharmony_ci .err_info_init = sec_err_info_init, 105762306a36Sopenharmony_ci}; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_cistatic int sec_pf_probe_init(struct sec_dev *sec) 106062306a36Sopenharmony_ci{ 106162306a36Sopenharmony_ci struct hisi_qm *qm = &sec->qm; 106262306a36Sopenharmony_ci int ret; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci qm->err_ini = &sec_err_ini; 106562306a36Sopenharmony_ci qm->err_ini->err_info_init(qm); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci ret = sec_set_user_domain_and_cache(qm); 106862306a36Sopenharmony_ci if (ret) 106962306a36Sopenharmony_ci return ret; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci sec_open_sva_prefetch(qm); 107262306a36Sopenharmony_ci hisi_qm_dev_err_init(qm); 107362306a36Sopenharmony_ci sec_debug_regs_clear(qm); 107462306a36Sopenharmony_ci ret = sec_show_last_regs_init(qm); 107562306a36Sopenharmony_ci if (ret) 107662306a36Sopenharmony_ci pci_err(qm->pdev, "Failed to init last word regs!\n"); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci return ret; 107962306a36Sopenharmony_ci} 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_cistatic int sec_pre_store_cap_reg(struct hisi_qm *qm) 108262306a36Sopenharmony_ci{ 108362306a36Sopenharmony_ci struct hisi_qm_cap_record *sec_cap; 108462306a36Sopenharmony_ci struct pci_dev *pdev = qm->pdev; 108562306a36Sopenharmony_ci size_t i, size; 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci size = ARRAY_SIZE(sec_pre_store_caps); 108862306a36Sopenharmony_ci sec_cap = devm_kzalloc(&pdev->dev, sizeof(*sec_cap) * size, GFP_KERNEL); 108962306a36Sopenharmony_ci if (!sec_cap) 109062306a36Sopenharmony_ci return -ENOMEM; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci for (i = 0; i < size; i++) { 109362306a36Sopenharmony_ci sec_cap[i].type = sec_pre_store_caps[i]; 109462306a36Sopenharmony_ci sec_cap[i].cap_val = hisi_qm_get_hw_info(qm, sec_basic_info, 109562306a36Sopenharmony_ci sec_pre_store_caps[i], qm->cap_ver); 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci qm->cap_tables.dev_cap_table = sec_cap; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci return 0; 110162306a36Sopenharmony_ci} 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) 110462306a36Sopenharmony_ci{ 110562306a36Sopenharmony_ci u64 alg_msk; 110662306a36Sopenharmony_ci int ret; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci qm->pdev = pdev; 110962306a36Sopenharmony_ci qm->ver = pdev->revision; 111062306a36Sopenharmony_ci qm->mode = uacce_mode; 111162306a36Sopenharmony_ci qm->sqe_size = SEC_SQE_SIZE; 111262306a36Sopenharmony_ci qm->dev_name = sec_name; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci qm->fun_type = (pdev->device == PCI_DEVICE_ID_HUAWEI_SEC_PF) ? 111562306a36Sopenharmony_ci QM_HW_PF : QM_HW_VF; 111662306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF) { 111762306a36Sopenharmony_ci qm->qp_base = SEC_PF_DEF_Q_BASE; 111862306a36Sopenharmony_ci qm->qp_num = pf_q_num; 111962306a36Sopenharmony_ci qm->debug.curr_qm_qp_num = pf_q_num; 112062306a36Sopenharmony_ci qm->qm_list = &sec_devices; 112162306a36Sopenharmony_ci if (pf_q_num_flag) 112262306a36Sopenharmony_ci set_bit(QM_MODULE_PARAM, &qm->misc_ctl); 112362306a36Sopenharmony_ci } else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) { 112462306a36Sopenharmony_ci /* 112562306a36Sopenharmony_ci * have no way to get qm configure in VM in v1 hardware, 112662306a36Sopenharmony_ci * so currently force PF to uses SEC_PF_DEF_Q_NUM, and force 112762306a36Sopenharmony_ci * to trigger only one VF in v1 hardware. 112862306a36Sopenharmony_ci * v2 hardware has no such problem. 112962306a36Sopenharmony_ci */ 113062306a36Sopenharmony_ci qm->qp_base = SEC_PF_DEF_Q_NUM; 113162306a36Sopenharmony_ci qm->qp_num = SEC_QUEUE_NUM_V1 - SEC_PF_DEF_Q_NUM; 113262306a36Sopenharmony_ci } 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci ret = hisi_qm_init(qm); 113562306a36Sopenharmony_ci if (ret) { 113662306a36Sopenharmony_ci pci_err(qm->pdev, "Failed to init sec qm configures!\n"); 113762306a36Sopenharmony_ci return ret; 113862306a36Sopenharmony_ci } 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci /* Fetch and save the value of capability registers */ 114162306a36Sopenharmony_ci ret = sec_pre_store_cap_reg(qm); 114262306a36Sopenharmony_ci if (ret) { 114362306a36Sopenharmony_ci pci_err(qm->pdev, "Failed to pre-store capability registers!\n"); 114462306a36Sopenharmony_ci hisi_qm_uninit(qm); 114562306a36Sopenharmony_ci return ret; 114662306a36Sopenharmony_ci } 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci alg_msk = sec_get_alg_bitmap(qm, SEC_DEV_ALG_BITMAP_HIGH_IDX, SEC_DEV_ALG_BITMAP_LOW_IDX); 114962306a36Sopenharmony_ci ret = hisi_qm_set_algs(qm, alg_msk, sec_dev_algs, ARRAY_SIZE(sec_dev_algs)); 115062306a36Sopenharmony_ci if (ret) { 115162306a36Sopenharmony_ci pci_err(qm->pdev, "Failed to set sec algs!\n"); 115262306a36Sopenharmony_ci hisi_qm_uninit(qm); 115362306a36Sopenharmony_ci } 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci return ret; 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_cistatic void sec_qm_uninit(struct hisi_qm *qm) 115962306a36Sopenharmony_ci{ 116062306a36Sopenharmony_ci hisi_qm_uninit(qm); 116162306a36Sopenharmony_ci} 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_cistatic int sec_probe_init(struct sec_dev *sec) 116462306a36Sopenharmony_ci{ 116562306a36Sopenharmony_ci u32 type_rate = SEC_SHAPER_TYPE_RATE; 116662306a36Sopenharmony_ci struct hisi_qm *qm = &sec->qm; 116762306a36Sopenharmony_ci int ret; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF) { 117062306a36Sopenharmony_ci ret = sec_pf_probe_init(sec); 117162306a36Sopenharmony_ci if (ret) 117262306a36Sopenharmony_ci return ret; 117362306a36Sopenharmony_ci /* enable shaper type 0 */ 117462306a36Sopenharmony_ci if (qm->ver >= QM_HW_V3) { 117562306a36Sopenharmony_ci type_rate |= QM_SHAPER_ENABLE; 117662306a36Sopenharmony_ci qm->type_rate = type_rate; 117762306a36Sopenharmony_ci } 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci return 0; 118162306a36Sopenharmony_ci} 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_cistatic void sec_probe_uninit(struct hisi_qm *qm) 118462306a36Sopenharmony_ci{ 118562306a36Sopenharmony_ci hisi_qm_dev_err_uninit(qm); 118662306a36Sopenharmony_ci} 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_cistatic void sec_iommu_used_check(struct sec_dev *sec) 118962306a36Sopenharmony_ci{ 119062306a36Sopenharmony_ci struct iommu_domain *domain; 119162306a36Sopenharmony_ci struct device *dev = &sec->qm.pdev->dev; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci domain = iommu_get_domain_for_dev(dev); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci /* Check if iommu is used */ 119662306a36Sopenharmony_ci sec->iommu_used = false; 119762306a36Sopenharmony_ci if (domain) { 119862306a36Sopenharmony_ci if (domain->type & __IOMMU_DOMAIN_PAGING) 119962306a36Sopenharmony_ci sec->iommu_used = true; 120062306a36Sopenharmony_ci dev_info(dev, "SMMU Opened, the iommu type = %u\n", 120162306a36Sopenharmony_ci domain->type); 120262306a36Sopenharmony_ci } 120362306a36Sopenharmony_ci} 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_cistatic int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) 120662306a36Sopenharmony_ci{ 120762306a36Sopenharmony_ci struct sec_dev *sec; 120862306a36Sopenharmony_ci struct hisi_qm *qm; 120962306a36Sopenharmony_ci int ret; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL); 121262306a36Sopenharmony_ci if (!sec) 121362306a36Sopenharmony_ci return -ENOMEM; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci qm = &sec->qm; 121662306a36Sopenharmony_ci ret = sec_qm_init(qm, pdev); 121762306a36Sopenharmony_ci if (ret) { 121862306a36Sopenharmony_ci pci_err(pdev, "Failed to init SEC QM (%d)!\n", ret); 121962306a36Sopenharmony_ci return ret; 122062306a36Sopenharmony_ci } 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci sec->ctx_q_num = ctx_q_num; 122362306a36Sopenharmony_ci sec_iommu_used_check(sec); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci ret = sec_probe_init(sec); 122662306a36Sopenharmony_ci if (ret) { 122762306a36Sopenharmony_ci pci_err(pdev, "Failed to probe!\n"); 122862306a36Sopenharmony_ci goto err_qm_uninit; 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci ret = hisi_qm_start(qm); 123262306a36Sopenharmony_ci if (ret) { 123362306a36Sopenharmony_ci pci_err(pdev, "Failed to start sec qm!\n"); 123462306a36Sopenharmony_ci goto err_probe_uninit; 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci ret = sec_debugfs_init(qm); 123862306a36Sopenharmony_ci if (ret) 123962306a36Sopenharmony_ci pci_warn(pdev, "Failed to init debugfs!\n"); 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci if (qm->qp_num >= ctx_q_num) { 124262306a36Sopenharmony_ci ret = hisi_qm_alg_register(qm, &sec_devices); 124362306a36Sopenharmony_ci if (ret < 0) { 124462306a36Sopenharmony_ci pr_err("Failed to register driver to crypto.\n"); 124562306a36Sopenharmony_ci goto err_qm_stop; 124662306a36Sopenharmony_ci } 124762306a36Sopenharmony_ci } else { 124862306a36Sopenharmony_ci pci_warn(qm->pdev, 124962306a36Sopenharmony_ci "Failed to use kernel mode, qp not enough!\n"); 125062306a36Sopenharmony_ci } 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci if (qm->uacce) { 125362306a36Sopenharmony_ci ret = uacce_register(qm->uacce); 125462306a36Sopenharmony_ci if (ret) { 125562306a36Sopenharmony_ci pci_err(pdev, "failed to register uacce (%d)!\n", ret); 125662306a36Sopenharmony_ci goto err_alg_unregister; 125762306a36Sopenharmony_ci } 125862306a36Sopenharmony_ci } 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF && vfs_num) { 126162306a36Sopenharmony_ci ret = hisi_qm_sriov_enable(pdev, vfs_num); 126262306a36Sopenharmony_ci if (ret < 0) 126362306a36Sopenharmony_ci goto err_alg_unregister; 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci hisi_qm_pm_init(qm); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci return 0; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_cierr_alg_unregister: 127162306a36Sopenharmony_ci if (qm->qp_num >= ctx_q_num) 127262306a36Sopenharmony_ci hisi_qm_alg_unregister(qm, &sec_devices); 127362306a36Sopenharmony_cierr_qm_stop: 127462306a36Sopenharmony_ci sec_debugfs_exit(qm); 127562306a36Sopenharmony_ci hisi_qm_stop(qm, QM_NORMAL); 127662306a36Sopenharmony_cierr_probe_uninit: 127762306a36Sopenharmony_ci sec_show_last_regs_uninit(qm); 127862306a36Sopenharmony_ci sec_probe_uninit(qm); 127962306a36Sopenharmony_cierr_qm_uninit: 128062306a36Sopenharmony_ci sec_qm_uninit(qm); 128162306a36Sopenharmony_ci return ret; 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_cistatic void sec_remove(struct pci_dev *pdev) 128562306a36Sopenharmony_ci{ 128662306a36Sopenharmony_ci struct hisi_qm *qm = pci_get_drvdata(pdev); 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci hisi_qm_pm_uninit(qm); 128962306a36Sopenharmony_ci hisi_qm_wait_task_finish(qm, &sec_devices); 129062306a36Sopenharmony_ci if (qm->qp_num >= ctx_q_num) 129162306a36Sopenharmony_ci hisi_qm_alg_unregister(qm, &sec_devices); 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF && qm->vfs_num) 129462306a36Sopenharmony_ci hisi_qm_sriov_disable(pdev, true); 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci sec_debugfs_exit(qm); 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci (void)hisi_qm_stop(qm, QM_NORMAL); 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF) 130162306a36Sopenharmony_ci sec_debug_regs_clear(qm); 130262306a36Sopenharmony_ci sec_show_last_regs_uninit(qm); 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci sec_probe_uninit(qm); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci sec_qm_uninit(qm); 130762306a36Sopenharmony_ci} 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_cistatic const struct dev_pm_ops sec_pm_ops = { 131062306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(hisi_qm_suspend, hisi_qm_resume, NULL) 131162306a36Sopenharmony_ci}; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_cistatic const struct pci_error_handlers sec_err_handler = { 131462306a36Sopenharmony_ci .error_detected = hisi_qm_dev_err_detected, 131562306a36Sopenharmony_ci .slot_reset = hisi_qm_dev_slot_reset, 131662306a36Sopenharmony_ci .reset_prepare = hisi_qm_reset_prepare, 131762306a36Sopenharmony_ci .reset_done = hisi_qm_reset_done, 131862306a36Sopenharmony_ci}; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_cistatic struct pci_driver sec_pci_driver = { 132162306a36Sopenharmony_ci .name = "hisi_sec2", 132262306a36Sopenharmony_ci .id_table = sec_dev_ids, 132362306a36Sopenharmony_ci .probe = sec_probe, 132462306a36Sopenharmony_ci .remove = sec_remove, 132562306a36Sopenharmony_ci .err_handler = &sec_err_handler, 132662306a36Sopenharmony_ci .sriov_configure = hisi_qm_sriov_configure, 132762306a36Sopenharmony_ci .shutdown = hisi_qm_dev_shutdown, 132862306a36Sopenharmony_ci .driver.pm = &sec_pm_ops, 132962306a36Sopenharmony_ci}; 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_cistruct pci_driver *hisi_sec_get_pf_driver(void) 133262306a36Sopenharmony_ci{ 133362306a36Sopenharmony_ci return &sec_pci_driver; 133462306a36Sopenharmony_ci} 133562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_sec_get_pf_driver); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_cistatic void sec_register_debugfs(void) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci if (!debugfs_initialized()) 134062306a36Sopenharmony_ci return; 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci sec_debugfs_root = debugfs_create_dir("hisi_sec2", NULL); 134362306a36Sopenharmony_ci} 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_cistatic void sec_unregister_debugfs(void) 134662306a36Sopenharmony_ci{ 134762306a36Sopenharmony_ci debugfs_remove_recursive(sec_debugfs_root); 134862306a36Sopenharmony_ci} 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_cistatic int __init sec_init(void) 135162306a36Sopenharmony_ci{ 135262306a36Sopenharmony_ci int ret; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci hisi_qm_init_list(&sec_devices); 135562306a36Sopenharmony_ci sec_register_debugfs(); 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci ret = pci_register_driver(&sec_pci_driver); 135862306a36Sopenharmony_ci if (ret < 0) { 135962306a36Sopenharmony_ci sec_unregister_debugfs(); 136062306a36Sopenharmony_ci pr_err("Failed to register pci driver.\n"); 136162306a36Sopenharmony_ci return ret; 136262306a36Sopenharmony_ci } 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci return 0; 136562306a36Sopenharmony_ci} 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_cistatic void __exit sec_exit(void) 136862306a36Sopenharmony_ci{ 136962306a36Sopenharmony_ci pci_unregister_driver(&sec_pci_driver); 137062306a36Sopenharmony_ci sec_unregister_debugfs(); 137162306a36Sopenharmony_ci} 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_cimodule_init(sec_init); 137462306a36Sopenharmony_cimodule_exit(sec_exit); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 137762306a36Sopenharmony_ciMODULE_AUTHOR("Zaibo Xu <xuzaibo@huawei.com>"); 137862306a36Sopenharmony_ciMODULE_AUTHOR("Longfang Liu <liulongfang@huawei.com>"); 137962306a36Sopenharmony_ciMODULE_AUTHOR("Kai Ye <yekai13@huawei.com>"); 138062306a36Sopenharmony_ciMODULE_AUTHOR("Wei Zhang <zhangwei375@huawei.com>"); 138162306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver for HiSilicon SEC accelerator"); 1382