162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2018-2019 HiSilicon Limited. */ 362306a36Sopenharmony_ci#include <linux/acpi.h> 462306a36Sopenharmony_ci#include <linux/bitops.h> 562306a36Sopenharmony_ci#include <linux/debugfs.h> 662306a36Sopenharmony_ci#include <linux/init.h> 762306a36Sopenharmony_ci#include <linux/io.h> 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/pci.h> 1162306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1262306a36Sopenharmony_ci#include <linux/topology.h> 1362306a36Sopenharmony_ci#include <linux/uacce.h> 1462306a36Sopenharmony_ci#include "hpre.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define HPRE_QM_ABNML_INT_MASK 0x100004 1762306a36Sopenharmony_ci#define HPRE_CTRL_CNT_CLR_CE_BIT BIT(0) 1862306a36Sopenharmony_ci#define HPRE_COMM_CNT_CLR_CE 0x0 1962306a36Sopenharmony_ci#define HPRE_CTRL_CNT_CLR_CE 0x301000 2062306a36Sopenharmony_ci#define HPRE_FSM_MAX_CNT 0x301008 2162306a36Sopenharmony_ci#define HPRE_VFG_AXQOS 0x30100c 2262306a36Sopenharmony_ci#define HPRE_VFG_AXCACHE 0x301010 2362306a36Sopenharmony_ci#define HPRE_RDCHN_INI_CFG 0x301014 2462306a36Sopenharmony_ci#define HPRE_AWUSR_FP_CFG 0x301018 2562306a36Sopenharmony_ci#define HPRE_BD_ENDIAN 0x301020 2662306a36Sopenharmony_ci#define HPRE_ECC_BYPASS 0x301024 2762306a36Sopenharmony_ci#define HPRE_RAS_WIDTH_CFG 0x301028 2862306a36Sopenharmony_ci#define HPRE_POISON_BYPASS 0x30102c 2962306a36Sopenharmony_ci#define HPRE_BD_ARUSR_CFG 0x301030 3062306a36Sopenharmony_ci#define HPRE_BD_AWUSR_CFG 0x301034 3162306a36Sopenharmony_ci#define HPRE_TYPES_ENB 0x301038 3262306a36Sopenharmony_ci#define HPRE_RSA_ENB BIT(0) 3362306a36Sopenharmony_ci#define HPRE_ECC_ENB BIT(1) 3462306a36Sopenharmony_ci#define HPRE_DATA_RUSER_CFG 0x30103c 3562306a36Sopenharmony_ci#define HPRE_DATA_WUSER_CFG 0x301040 3662306a36Sopenharmony_ci#define HPRE_INT_MASK 0x301400 3762306a36Sopenharmony_ci#define HPRE_INT_STATUS 0x301800 3862306a36Sopenharmony_ci#define HPRE_HAC_INT_MSK 0x301400 3962306a36Sopenharmony_ci#define HPRE_HAC_RAS_CE_ENB 0x301410 4062306a36Sopenharmony_ci#define HPRE_HAC_RAS_NFE_ENB 0x301414 4162306a36Sopenharmony_ci#define HPRE_HAC_RAS_FE_ENB 0x301418 4262306a36Sopenharmony_ci#define HPRE_HAC_INT_SET 0x301500 4362306a36Sopenharmony_ci#define HPRE_RNG_TIMEOUT_NUM 0x301A34 4462306a36Sopenharmony_ci#define HPRE_CORE_INT_ENABLE 0 4562306a36Sopenharmony_ci#define HPRE_CORE_INT_DISABLE GENMASK(21, 0) 4662306a36Sopenharmony_ci#define HPRE_RDCHN_INI_ST 0x301a00 4762306a36Sopenharmony_ci#define HPRE_CLSTR_BASE 0x302000 4862306a36Sopenharmony_ci#define HPRE_CORE_EN_OFFSET 0x04 4962306a36Sopenharmony_ci#define HPRE_CORE_INI_CFG_OFFSET 0x20 5062306a36Sopenharmony_ci#define HPRE_CORE_INI_STATUS_OFFSET 0x80 5162306a36Sopenharmony_ci#define HPRE_CORE_HTBT_WARN_OFFSET 0x8c 5262306a36Sopenharmony_ci#define HPRE_CORE_IS_SCHD_OFFSET 0x90 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define HPRE_RAS_CE_ENB 0x301410 5562306a36Sopenharmony_ci#define HPRE_RAS_NFE_ENB 0x301414 5662306a36Sopenharmony_ci#define HPRE_RAS_FE_ENB 0x301418 5762306a36Sopenharmony_ci#define HPRE_OOO_SHUTDOWN_SEL 0x301a3c 5862306a36Sopenharmony_ci#define HPRE_HAC_RAS_FE_ENABLE 0 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define HPRE_CORE_ENB (HPRE_CLSTR_BASE + HPRE_CORE_EN_OFFSET) 6162306a36Sopenharmony_ci#define HPRE_CORE_INI_CFG (HPRE_CLSTR_BASE + HPRE_CORE_INI_CFG_OFFSET) 6262306a36Sopenharmony_ci#define HPRE_CORE_INI_STATUS (HPRE_CLSTR_BASE + HPRE_CORE_INI_STATUS_OFFSET) 6362306a36Sopenharmony_ci#define HPRE_HAC_ECC1_CNT 0x301a04 6462306a36Sopenharmony_ci#define HPRE_HAC_ECC2_CNT 0x301a08 6562306a36Sopenharmony_ci#define HPRE_HAC_SOURCE_INT 0x301600 6662306a36Sopenharmony_ci#define HPRE_CLSTR_ADDR_INTRVL 0x1000 6762306a36Sopenharmony_ci#define HPRE_CLUSTER_INQURY 0x100 6862306a36Sopenharmony_ci#define HPRE_CLSTR_ADDR_INQRY_RSLT 0x104 6962306a36Sopenharmony_ci#define HPRE_TIMEOUT_ABNML_BIT 6 7062306a36Sopenharmony_ci#define HPRE_PASID_EN_BIT 9 7162306a36Sopenharmony_ci#define HPRE_REG_RD_INTVRL_US 10 7262306a36Sopenharmony_ci#define HPRE_REG_RD_TMOUT_US 1000 7362306a36Sopenharmony_ci#define HPRE_DBGFS_VAL_MAX_LEN 20 7462306a36Sopenharmony_ci#define PCI_DEVICE_ID_HUAWEI_HPRE_PF 0xa258 7562306a36Sopenharmony_ci#define HPRE_QM_USR_CFG_MASK GENMASK(31, 1) 7662306a36Sopenharmony_ci#define HPRE_QM_AXI_CFG_MASK GENMASK(15, 0) 7762306a36Sopenharmony_ci#define HPRE_QM_VFG_AX_MASK GENMASK(7, 0) 7862306a36Sopenharmony_ci#define HPRE_BD_USR_MASK GENMASK(1, 0) 7962306a36Sopenharmony_ci#define HPRE_PREFETCH_CFG 0x301130 8062306a36Sopenharmony_ci#define HPRE_SVA_PREFTCH_DFX 0x30115C 8162306a36Sopenharmony_ci#define HPRE_PREFETCH_ENABLE (~(BIT(0) | BIT(30))) 8262306a36Sopenharmony_ci#define HPRE_PREFETCH_DISABLE BIT(30) 8362306a36Sopenharmony_ci#define HPRE_SVA_DISABLE_READY (BIT(4) | BIT(8)) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* clock gate */ 8662306a36Sopenharmony_ci#define HPRE_CLKGATE_CTL 0x301a10 8762306a36Sopenharmony_ci#define HPRE_PEH_CFG_AUTO_GATE 0x301a2c 8862306a36Sopenharmony_ci#define HPRE_CLUSTER_DYN_CTL 0x302010 8962306a36Sopenharmony_ci#define HPRE_CORE_SHB_CFG 0x302088 9062306a36Sopenharmony_ci#define HPRE_CLKGATE_CTL_EN BIT(0) 9162306a36Sopenharmony_ci#define HPRE_PEH_CFG_AUTO_GATE_EN BIT(0) 9262306a36Sopenharmony_ci#define HPRE_CLUSTER_DYN_CTL_EN BIT(0) 9362306a36Sopenharmony_ci#define HPRE_CORE_GATE_EN (BIT(30) | BIT(31)) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#define HPRE_AM_OOO_SHUTDOWN_ENB 0x301044 9662306a36Sopenharmony_ci#define HPRE_AM_OOO_SHUTDOWN_ENABLE BIT(0) 9762306a36Sopenharmony_ci#define HPRE_WR_MSI_PORT BIT(2) 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#define HPRE_CORE_ECC_2BIT_ERR BIT(1) 10062306a36Sopenharmony_ci#define HPRE_OOO_ECC_2BIT_ERR BIT(5) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#define HPRE_QM_BME_FLR BIT(7) 10362306a36Sopenharmony_ci#define HPRE_QM_PM_FLR BIT(11) 10462306a36Sopenharmony_ci#define HPRE_QM_SRIOV_FLR BIT(12) 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define HPRE_SHAPER_TYPE_RATE 640 10762306a36Sopenharmony_ci#define HPRE_VIA_MSI_DSM 1 10862306a36Sopenharmony_ci#define HPRE_SQE_MASK_OFFSET 8 10962306a36Sopenharmony_ci#define HPRE_SQE_MASK_LEN 24 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci#define HPRE_DFX_BASE 0x301000 11262306a36Sopenharmony_ci#define HPRE_DFX_COMMON1 0x301400 11362306a36Sopenharmony_ci#define HPRE_DFX_COMMON2 0x301A00 11462306a36Sopenharmony_ci#define HPRE_DFX_CORE 0x302000 11562306a36Sopenharmony_ci#define HPRE_DFX_BASE_LEN 0x55 11662306a36Sopenharmony_ci#define HPRE_DFX_COMMON1_LEN 0x41 11762306a36Sopenharmony_ci#define HPRE_DFX_COMMON2_LEN 0xE 11862306a36Sopenharmony_ci#define HPRE_DFX_CORE_LEN 0x43 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic const char hpre_name[] = "hisi_hpre"; 12162306a36Sopenharmony_cistatic struct dentry *hpre_debugfs_root; 12262306a36Sopenharmony_cistatic const struct pci_device_id hpre_dev_ids[] = { 12362306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HUAWEI_HPRE_PF) }, 12462306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HUAWEI_HPRE_VF) }, 12562306a36Sopenharmony_ci { 0, } 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, hpre_dev_ids); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistruct hpre_hw_error { 13162306a36Sopenharmony_ci u32 int_msk; 13262306a36Sopenharmony_ci const char *msg; 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic const struct qm_dev_alg hpre_dev_algs[] = { 13662306a36Sopenharmony_ci { 13762306a36Sopenharmony_ci .alg_msk = BIT(0), 13862306a36Sopenharmony_ci .alg = "rsa\n" 13962306a36Sopenharmony_ci }, { 14062306a36Sopenharmony_ci .alg_msk = BIT(1), 14162306a36Sopenharmony_ci .alg = "dh\n" 14262306a36Sopenharmony_ci }, { 14362306a36Sopenharmony_ci .alg_msk = BIT(2), 14462306a36Sopenharmony_ci .alg = "ecdh\n" 14562306a36Sopenharmony_ci }, { 14662306a36Sopenharmony_ci .alg_msk = BIT(3), 14762306a36Sopenharmony_ci .alg = "ecdsa\n" 14862306a36Sopenharmony_ci }, { 14962306a36Sopenharmony_ci .alg_msk = BIT(4), 15062306a36Sopenharmony_ci .alg = "sm2\n" 15162306a36Sopenharmony_ci }, { 15262306a36Sopenharmony_ci .alg_msk = BIT(5), 15362306a36Sopenharmony_ci .alg = "x25519\n" 15462306a36Sopenharmony_ci }, { 15562306a36Sopenharmony_ci .alg_msk = BIT(6), 15662306a36Sopenharmony_ci .alg = "x448\n" 15762306a36Sopenharmony_ci }, { 15862306a36Sopenharmony_ci /* sentinel */ 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci}; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic struct hisi_qm_list hpre_devices = { 16362306a36Sopenharmony_ci .register_to_crypto = hpre_algs_register, 16462306a36Sopenharmony_ci .unregister_from_crypto = hpre_algs_unregister, 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic const char * const hpre_debug_file_name[] = { 16862306a36Sopenharmony_ci [HPRE_CLEAR_ENABLE] = "rdclr_en", 16962306a36Sopenharmony_ci [HPRE_CLUSTER_CTRL] = "cluster_ctrl", 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cienum hpre_cap_type { 17362306a36Sopenharmony_ci HPRE_QM_NFE_MASK_CAP, 17462306a36Sopenharmony_ci HPRE_QM_RESET_MASK_CAP, 17562306a36Sopenharmony_ci HPRE_QM_OOO_SHUTDOWN_MASK_CAP, 17662306a36Sopenharmony_ci HPRE_QM_CE_MASK_CAP, 17762306a36Sopenharmony_ci HPRE_NFE_MASK_CAP, 17862306a36Sopenharmony_ci HPRE_RESET_MASK_CAP, 17962306a36Sopenharmony_ci HPRE_OOO_SHUTDOWN_MASK_CAP, 18062306a36Sopenharmony_ci HPRE_CE_MASK_CAP, 18162306a36Sopenharmony_ci HPRE_CLUSTER_NUM_CAP, 18262306a36Sopenharmony_ci HPRE_CORE_TYPE_NUM_CAP, 18362306a36Sopenharmony_ci HPRE_CORE_NUM_CAP, 18462306a36Sopenharmony_ci HPRE_CLUSTER_CORE_NUM_CAP, 18562306a36Sopenharmony_ci HPRE_CORE_ENABLE_BITMAP_CAP, 18662306a36Sopenharmony_ci HPRE_DRV_ALG_BITMAP_CAP, 18762306a36Sopenharmony_ci HPRE_DEV_ALG_BITMAP_CAP, 18862306a36Sopenharmony_ci HPRE_CORE1_ALG_BITMAP_CAP, 18962306a36Sopenharmony_ci HPRE_CORE2_ALG_BITMAP_CAP, 19062306a36Sopenharmony_ci HPRE_CORE3_ALG_BITMAP_CAP, 19162306a36Sopenharmony_ci HPRE_CORE4_ALG_BITMAP_CAP, 19262306a36Sopenharmony_ci HPRE_CORE5_ALG_BITMAP_CAP, 19362306a36Sopenharmony_ci HPRE_CORE6_ALG_BITMAP_CAP, 19462306a36Sopenharmony_ci HPRE_CORE7_ALG_BITMAP_CAP, 19562306a36Sopenharmony_ci HPRE_CORE8_ALG_BITMAP_CAP, 19662306a36Sopenharmony_ci HPRE_CORE9_ALG_BITMAP_CAP, 19762306a36Sopenharmony_ci HPRE_CORE10_ALG_BITMAP_CAP 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic const struct hisi_qm_cap_info hpre_basic_info[] = { 20162306a36Sopenharmony_ci {HPRE_QM_NFE_MASK_CAP, 0x3124, 0, GENMASK(31, 0), 0x0, 0x1C37, 0x7C37}, 20262306a36Sopenharmony_ci {HPRE_QM_RESET_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0xC37, 0x6C37}, 20362306a36Sopenharmony_ci {HPRE_QM_OOO_SHUTDOWN_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0x4, 0x6C37}, 20462306a36Sopenharmony_ci {HPRE_QM_CE_MASK_CAP, 0x312C, 0, GENMASK(31, 0), 0x0, 0x8, 0x8}, 20562306a36Sopenharmony_ci {HPRE_NFE_MASK_CAP, 0x3130, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0x1FFFFFE}, 20662306a36Sopenharmony_ci {HPRE_RESET_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0xBFFFFE}, 20762306a36Sopenharmony_ci {HPRE_OOO_SHUTDOWN_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x22, 0xBFFFFE}, 20862306a36Sopenharmony_ci {HPRE_CE_MASK_CAP, 0x3138, 0, GENMASK(31, 0), 0x0, 0x1, 0x1}, 20962306a36Sopenharmony_ci {HPRE_CLUSTER_NUM_CAP, 0x313c, 20, GENMASK(3, 0), 0x0, 0x4, 0x1}, 21062306a36Sopenharmony_ci {HPRE_CORE_TYPE_NUM_CAP, 0x313c, 16, GENMASK(3, 0), 0x0, 0x2, 0x2}, 21162306a36Sopenharmony_ci {HPRE_CORE_NUM_CAP, 0x313c, 8, GENMASK(7, 0), 0x0, 0x8, 0xA}, 21262306a36Sopenharmony_ci {HPRE_CLUSTER_CORE_NUM_CAP, 0x313c, 0, GENMASK(7, 0), 0x0, 0x2, 0xA}, 21362306a36Sopenharmony_ci {HPRE_CORE_ENABLE_BITMAP_CAP, 0x3140, 0, GENMASK(31, 0), 0x0, 0xF, 0x3FF}, 21462306a36Sopenharmony_ci {HPRE_DRV_ALG_BITMAP_CAP, 0x3144, 0, GENMASK(31, 0), 0x0, 0x03, 0x27}, 21562306a36Sopenharmony_ci {HPRE_DEV_ALG_BITMAP_CAP, 0x3148, 0, GENMASK(31, 0), 0x0, 0x03, 0x7F}, 21662306a36Sopenharmony_ci {HPRE_CORE1_ALG_BITMAP_CAP, 0x314c, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 21762306a36Sopenharmony_ci {HPRE_CORE2_ALG_BITMAP_CAP, 0x3150, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 21862306a36Sopenharmony_ci {HPRE_CORE3_ALG_BITMAP_CAP, 0x3154, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 21962306a36Sopenharmony_ci {HPRE_CORE4_ALG_BITMAP_CAP, 0x3158, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 22062306a36Sopenharmony_ci {HPRE_CORE5_ALG_BITMAP_CAP, 0x315c, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 22162306a36Sopenharmony_ci {HPRE_CORE6_ALG_BITMAP_CAP, 0x3160, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 22262306a36Sopenharmony_ci {HPRE_CORE7_ALG_BITMAP_CAP, 0x3164, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 22362306a36Sopenharmony_ci {HPRE_CORE8_ALG_BITMAP_CAP, 0x3168, 0, GENMASK(31, 0), 0x0, 0x7F, 0x7F}, 22462306a36Sopenharmony_ci {HPRE_CORE9_ALG_BITMAP_CAP, 0x316c, 0, GENMASK(31, 0), 0x0, 0x10, 0x10}, 22562306a36Sopenharmony_ci {HPRE_CORE10_ALG_BITMAP_CAP, 0x3170, 0, GENMASK(31, 0), 0x0, 0x10, 0x10} 22662306a36Sopenharmony_ci}; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cienum hpre_pre_store_cap_idx { 22962306a36Sopenharmony_ci HPRE_CLUSTER_NUM_CAP_IDX = 0x0, 23062306a36Sopenharmony_ci HPRE_CORE_ENABLE_BITMAP_CAP_IDX, 23162306a36Sopenharmony_ci HPRE_DRV_ALG_BITMAP_CAP_IDX, 23262306a36Sopenharmony_ci HPRE_DEV_ALG_BITMAP_CAP_IDX, 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic const u32 hpre_pre_store_caps[] = { 23662306a36Sopenharmony_ci HPRE_CLUSTER_NUM_CAP, 23762306a36Sopenharmony_ci HPRE_CORE_ENABLE_BITMAP_CAP, 23862306a36Sopenharmony_ci HPRE_DRV_ALG_BITMAP_CAP, 23962306a36Sopenharmony_ci HPRE_DEV_ALG_BITMAP_CAP, 24062306a36Sopenharmony_ci}; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic const struct hpre_hw_error hpre_hw_errors[] = { 24362306a36Sopenharmony_ci { 24462306a36Sopenharmony_ci .int_msk = BIT(0), 24562306a36Sopenharmony_ci .msg = "core_ecc_1bit_err_int_set" 24662306a36Sopenharmony_ci }, { 24762306a36Sopenharmony_ci .int_msk = BIT(1), 24862306a36Sopenharmony_ci .msg = "core_ecc_2bit_err_int_set" 24962306a36Sopenharmony_ci }, { 25062306a36Sopenharmony_ci .int_msk = BIT(2), 25162306a36Sopenharmony_ci .msg = "dat_wb_poison_int_set" 25262306a36Sopenharmony_ci }, { 25362306a36Sopenharmony_ci .int_msk = BIT(3), 25462306a36Sopenharmony_ci .msg = "dat_rd_poison_int_set" 25562306a36Sopenharmony_ci }, { 25662306a36Sopenharmony_ci .int_msk = BIT(4), 25762306a36Sopenharmony_ci .msg = "bd_rd_poison_int_set" 25862306a36Sopenharmony_ci }, { 25962306a36Sopenharmony_ci .int_msk = BIT(5), 26062306a36Sopenharmony_ci .msg = "ooo_ecc_2bit_err_int_set" 26162306a36Sopenharmony_ci }, { 26262306a36Sopenharmony_ci .int_msk = BIT(6), 26362306a36Sopenharmony_ci .msg = "cluster1_shb_timeout_int_set" 26462306a36Sopenharmony_ci }, { 26562306a36Sopenharmony_ci .int_msk = BIT(7), 26662306a36Sopenharmony_ci .msg = "cluster2_shb_timeout_int_set" 26762306a36Sopenharmony_ci }, { 26862306a36Sopenharmony_ci .int_msk = BIT(8), 26962306a36Sopenharmony_ci .msg = "cluster3_shb_timeout_int_set" 27062306a36Sopenharmony_ci }, { 27162306a36Sopenharmony_ci .int_msk = BIT(9), 27262306a36Sopenharmony_ci .msg = "cluster4_shb_timeout_int_set" 27362306a36Sopenharmony_ci }, { 27462306a36Sopenharmony_ci .int_msk = GENMASK(15, 10), 27562306a36Sopenharmony_ci .msg = "ooo_rdrsp_err_int_set" 27662306a36Sopenharmony_ci }, { 27762306a36Sopenharmony_ci .int_msk = GENMASK(21, 16), 27862306a36Sopenharmony_ci .msg = "ooo_wrrsp_err_int_set" 27962306a36Sopenharmony_ci }, { 28062306a36Sopenharmony_ci .int_msk = BIT(22), 28162306a36Sopenharmony_ci .msg = "pt_rng_timeout_int_set" 28262306a36Sopenharmony_ci }, { 28362306a36Sopenharmony_ci .int_msk = BIT(23), 28462306a36Sopenharmony_ci .msg = "sva_fsm_timeout_int_set" 28562306a36Sopenharmony_ci }, { 28662306a36Sopenharmony_ci .int_msk = BIT(24), 28762306a36Sopenharmony_ci .msg = "sva_int_set" 28862306a36Sopenharmony_ci }, { 28962306a36Sopenharmony_ci /* sentinel */ 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci}; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic const u64 hpre_cluster_offsets[] = { 29462306a36Sopenharmony_ci [HPRE_CLUSTER0] = 29562306a36Sopenharmony_ci HPRE_CLSTR_BASE + HPRE_CLUSTER0 * HPRE_CLSTR_ADDR_INTRVL, 29662306a36Sopenharmony_ci [HPRE_CLUSTER1] = 29762306a36Sopenharmony_ci HPRE_CLSTR_BASE + HPRE_CLUSTER1 * HPRE_CLSTR_ADDR_INTRVL, 29862306a36Sopenharmony_ci [HPRE_CLUSTER2] = 29962306a36Sopenharmony_ci HPRE_CLSTR_BASE + HPRE_CLUSTER2 * HPRE_CLSTR_ADDR_INTRVL, 30062306a36Sopenharmony_ci [HPRE_CLUSTER3] = 30162306a36Sopenharmony_ci HPRE_CLSTR_BASE + HPRE_CLUSTER3 * HPRE_CLSTR_ADDR_INTRVL, 30262306a36Sopenharmony_ci}; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic const struct debugfs_reg32 hpre_cluster_dfx_regs[] = { 30562306a36Sopenharmony_ci {"CORES_EN_STATUS ", HPRE_CORE_EN_OFFSET}, 30662306a36Sopenharmony_ci {"CORES_INI_CFG ", HPRE_CORE_INI_CFG_OFFSET}, 30762306a36Sopenharmony_ci {"CORES_INI_STATUS ", HPRE_CORE_INI_STATUS_OFFSET}, 30862306a36Sopenharmony_ci {"CORES_HTBT_WARN ", HPRE_CORE_HTBT_WARN_OFFSET}, 30962306a36Sopenharmony_ci {"CORES_IS_SCHD ", HPRE_CORE_IS_SCHD_OFFSET}, 31062306a36Sopenharmony_ci}; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic const struct debugfs_reg32 hpre_com_dfx_regs[] = { 31362306a36Sopenharmony_ci {"READ_CLR_EN ", HPRE_CTRL_CNT_CLR_CE}, 31462306a36Sopenharmony_ci {"AXQOS ", HPRE_VFG_AXQOS}, 31562306a36Sopenharmony_ci {"AWUSR_CFG ", HPRE_AWUSR_FP_CFG}, 31662306a36Sopenharmony_ci {"BD_ENDIAN ", HPRE_BD_ENDIAN}, 31762306a36Sopenharmony_ci {"ECC_CHECK_CTRL ", HPRE_ECC_BYPASS}, 31862306a36Sopenharmony_ci {"RAS_INT_WIDTH ", HPRE_RAS_WIDTH_CFG}, 31962306a36Sopenharmony_ci {"POISON_BYPASS ", HPRE_POISON_BYPASS}, 32062306a36Sopenharmony_ci {"BD_ARUSER ", HPRE_BD_ARUSR_CFG}, 32162306a36Sopenharmony_ci {"BD_AWUSER ", HPRE_BD_AWUSR_CFG}, 32262306a36Sopenharmony_ci {"DATA_ARUSER ", HPRE_DATA_RUSER_CFG}, 32362306a36Sopenharmony_ci {"DATA_AWUSER ", HPRE_DATA_WUSER_CFG}, 32462306a36Sopenharmony_ci {"INT_STATUS ", HPRE_INT_STATUS}, 32562306a36Sopenharmony_ci {"INT_MASK ", HPRE_HAC_INT_MSK}, 32662306a36Sopenharmony_ci {"RAS_CE_ENB ", HPRE_HAC_RAS_CE_ENB}, 32762306a36Sopenharmony_ci {"RAS_NFE_ENB ", HPRE_HAC_RAS_NFE_ENB}, 32862306a36Sopenharmony_ci {"RAS_FE_ENB ", HPRE_HAC_RAS_FE_ENB}, 32962306a36Sopenharmony_ci {"INT_SET ", HPRE_HAC_INT_SET}, 33062306a36Sopenharmony_ci {"RNG_TIMEOUT_NUM ", HPRE_RNG_TIMEOUT_NUM}, 33162306a36Sopenharmony_ci}; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic const char *hpre_dfx_files[HPRE_DFX_FILE_NUM] = { 33462306a36Sopenharmony_ci "send_cnt", 33562306a36Sopenharmony_ci "recv_cnt", 33662306a36Sopenharmony_ci "send_fail_cnt", 33762306a36Sopenharmony_ci "send_busy_cnt", 33862306a36Sopenharmony_ci "over_thrhld_cnt", 33962306a36Sopenharmony_ci "overtime_thrhld", 34062306a36Sopenharmony_ci "invalid_req_cnt" 34162306a36Sopenharmony_ci}; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci/* define the HPRE's dfx regs region and region length */ 34462306a36Sopenharmony_cistatic struct dfx_diff_registers hpre_diff_regs[] = { 34562306a36Sopenharmony_ci { 34662306a36Sopenharmony_ci .reg_offset = HPRE_DFX_BASE, 34762306a36Sopenharmony_ci .reg_len = HPRE_DFX_BASE_LEN, 34862306a36Sopenharmony_ci }, { 34962306a36Sopenharmony_ci .reg_offset = HPRE_DFX_COMMON1, 35062306a36Sopenharmony_ci .reg_len = HPRE_DFX_COMMON1_LEN, 35162306a36Sopenharmony_ci }, { 35262306a36Sopenharmony_ci .reg_offset = HPRE_DFX_COMMON2, 35362306a36Sopenharmony_ci .reg_len = HPRE_DFX_COMMON2_LEN, 35462306a36Sopenharmony_ci }, { 35562306a36Sopenharmony_ci .reg_offset = HPRE_DFX_CORE, 35662306a36Sopenharmony_ci .reg_len = HPRE_DFX_CORE_LEN, 35762306a36Sopenharmony_ci }, 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cibool hpre_check_alg_support(struct hisi_qm *qm, u32 alg) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci u32 cap_val; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci cap_val = qm->cap_tables.dev_cap_table[HPRE_DRV_ALG_BITMAP_CAP_IDX].cap_val; 36562306a36Sopenharmony_ci if (alg & cap_val) 36662306a36Sopenharmony_ci return true; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci return false; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic int hpre_diff_regs_show(struct seq_file *s, void *unused) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci struct hisi_qm *qm = s->private; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.acc_diff_regs, 37662306a36Sopenharmony_ci ARRAY_SIZE(hpre_diff_regs)); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci return 0; 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(hpre_diff_regs); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic int hpre_com_regs_show(struct seq_file *s, void *unused) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci hisi_qm_regs_dump(s, s->private); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci return 0; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(hpre_com_regs); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic int hpre_cluster_regs_show(struct seq_file *s, void *unused) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci hisi_qm_regs_dump(s, s->private); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci return 0; 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(hpre_cluster_regs); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic const struct kernel_param_ops hpre_uacce_mode_ops = { 40262306a36Sopenharmony_ci .set = uacce_mode_set, 40362306a36Sopenharmony_ci .get = param_get_int, 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci/* 40762306a36Sopenharmony_ci * uacce_mode = 0 means hpre only register to crypto, 40862306a36Sopenharmony_ci * uacce_mode = 1 means hpre both register to crypto and uacce. 40962306a36Sopenharmony_ci */ 41062306a36Sopenharmony_cistatic u32 uacce_mode = UACCE_MODE_NOUACCE; 41162306a36Sopenharmony_cimodule_param_cb(uacce_mode, &hpre_uacce_mode_ops, &uacce_mode, 0444); 41262306a36Sopenharmony_ciMODULE_PARM_DESC(uacce_mode, UACCE_MODE_DESC); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic bool pf_q_num_flag; 41562306a36Sopenharmony_cistatic int pf_q_num_set(const char *val, const struct kernel_param *kp) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci pf_q_num_flag = true; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_HPRE_PF); 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic const struct kernel_param_ops hpre_pf_q_num_ops = { 42362306a36Sopenharmony_ci .set = pf_q_num_set, 42462306a36Sopenharmony_ci .get = param_get_int, 42562306a36Sopenharmony_ci}; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic u32 pf_q_num = HPRE_PF_DEF_Q_NUM; 42862306a36Sopenharmony_cimodule_param_cb(pf_q_num, &hpre_pf_q_num_ops, &pf_q_num, 0444); 42962306a36Sopenharmony_ciMODULE_PARM_DESC(pf_q_num, "Number of queues in PF of CS(2-1024)"); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic const struct kernel_param_ops vfs_num_ops = { 43262306a36Sopenharmony_ci .set = vfs_num_set, 43362306a36Sopenharmony_ci .get = param_get_int, 43462306a36Sopenharmony_ci}; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic u32 vfs_num; 43762306a36Sopenharmony_cimodule_param_cb(vfs_num, &vfs_num_ops, &vfs_num, 0444); 43862306a36Sopenharmony_ciMODULE_PARM_DESC(vfs_num, "Number of VFs to enable(1-63), 0(default)"); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistruct hisi_qp *hpre_create_qp(u8 type) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci int node = cpu_to_node(smp_processor_id()); 44362306a36Sopenharmony_ci struct hisi_qp *qp = NULL; 44462306a36Sopenharmony_ci int ret; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (type != HPRE_V2_ALG_TYPE && type != HPRE_V3_ECC_ALG_TYPE) 44762306a36Sopenharmony_ci return NULL; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* 45062306a36Sopenharmony_ci * type: 0 - RSA/DH. algorithm supported in V2, 45162306a36Sopenharmony_ci * 1 - ECC algorithm in V3. 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci ret = hisi_qm_alloc_qps_node(&hpre_devices, 1, type, node, &qp); 45462306a36Sopenharmony_ci if (!ret) 45562306a36Sopenharmony_ci return qp; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci return NULL; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic void hpre_config_pasid(struct hisi_qm *qm) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci u32 val1, val2; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci if (qm->ver >= QM_HW_V3) 46562306a36Sopenharmony_ci return; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci val1 = readl_relaxed(qm->io_base + HPRE_DATA_RUSER_CFG); 46862306a36Sopenharmony_ci val2 = readl_relaxed(qm->io_base + HPRE_DATA_WUSER_CFG); 46962306a36Sopenharmony_ci if (qm->use_sva) { 47062306a36Sopenharmony_ci val1 |= BIT(HPRE_PASID_EN_BIT); 47162306a36Sopenharmony_ci val2 |= BIT(HPRE_PASID_EN_BIT); 47262306a36Sopenharmony_ci } else { 47362306a36Sopenharmony_ci val1 &= ~BIT(HPRE_PASID_EN_BIT); 47462306a36Sopenharmony_ci val2 &= ~BIT(HPRE_PASID_EN_BIT); 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci writel_relaxed(val1, qm->io_base + HPRE_DATA_RUSER_CFG); 47762306a36Sopenharmony_ci writel_relaxed(val2, qm->io_base + HPRE_DATA_WUSER_CFG); 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic int hpre_cfg_by_dsm(struct hisi_qm *qm) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 48362306a36Sopenharmony_ci union acpi_object *obj; 48462306a36Sopenharmony_ci guid_t guid; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci if (guid_parse("b06b81ab-0134-4a45-9b0c-483447b95fa7", &guid)) { 48762306a36Sopenharmony_ci dev_err(dev, "Hpre GUID failed\n"); 48862306a36Sopenharmony_ci return -EINVAL; 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci /* Switch over to MSI handling due to non-standard PCI implementation */ 49262306a36Sopenharmony_ci obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &guid, 49362306a36Sopenharmony_ci 0, HPRE_VIA_MSI_DSM, NULL); 49462306a36Sopenharmony_ci if (!obj) { 49562306a36Sopenharmony_ci dev_err(dev, "ACPI handle failed!\n"); 49662306a36Sopenharmony_ci return -EIO; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci ACPI_FREE(obj); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci return 0; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic int hpre_set_cluster(struct hisi_qm *qm) 50562306a36Sopenharmony_ci{ 50662306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 50762306a36Sopenharmony_ci unsigned long offset; 50862306a36Sopenharmony_ci u32 cluster_core_mask; 50962306a36Sopenharmony_ci u8 clusters_num; 51062306a36Sopenharmony_ci u32 val = 0; 51162306a36Sopenharmony_ci int ret, i; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci cluster_core_mask = qm->cap_tables.dev_cap_table[HPRE_CORE_ENABLE_BITMAP_CAP_IDX].cap_val; 51462306a36Sopenharmony_ci clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val; 51562306a36Sopenharmony_ci for (i = 0; i < clusters_num; i++) { 51662306a36Sopenharmony_ci offset = i * HPRE_CLSTR_ADDR_INTRVL; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* clusters initiating */ 51962306a36Sopenharmony_ci writel(cluster_core_mask, 52062306a36Sopenharmony_ci qm->io_base + offset + HPRE_CORE_ENB); 52162306a36Sopenharmony_ci writel(0x1, qm->io_base + offset + HPRE_CORE_INI_CFG); 52262306a36Sopenharmony_ci ret = readl_relaxed_poll_timeout(qm->io_base + offset + 52362306a36Sopenharmony_ci HPRE_CORE_INI_STATUS, val, 52462306a36Sopenharmony_ci ((val & cluster_core_mask) == 52562306a36Sopenharmony_ci cluster_core_mask), 52662306a36Sopenharmony_ci HPRE_REG_RD_INTVRL_US, 52762306a36Sopenharmony_ci HPRE_REG_RD_TMOUT_US); 52862306a36Sopenharmony_ci if (ret) { 52962306a36Sopenharmony_ci dev_err(dev, 53062306a36Sopenharmony_ci "cluster %d int st status timeout!\n", i); 53162306a36Sopenharmony_ci return -ETIMEDOUT; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci return 0; 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci/* 53962306a36Sopenharmony_ci * For Kunpeng 920, we should disable FLR triggered by hardware (BME/PM/SRIOV). 54062306a36Sopenharmony_ci * Or it may stay in D3 state when we bind and unbind hpre quickly, 54162306a36Sopenharmony_ci * as it does FLR triggered by hardware. 54262306a36Sopenharmony_ci */ 54362306a36Sopenharmony_cistatic void disable_flr_of_bme(struct hisi_qm *qm) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci u32 val; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci val = readl(qm->io_base + QM_PEH_AXUSER_CFG); 54862306a36Sopenharmony_ci val &= ~(HPRE_QM_BME_FLR | HPRE_QM_SRIOV_FLR); 54962306a36Sopenharmony_ci val |= HPRE_QM_PM_FLR; 55062306a36Sopenharmony_ci writel(val, qm->io_base + QM_PEH_AXUSER_CFG); 55162306a36Sopenharmony_ci writel(PEH_AXUSER_CFG_ENABLE, qm->io_base + QM_PEH_AXUSER_CFG_ENABLE); 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic void hpre_open_sva_prefetch(struct hisi_qm *qm) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci u32 val; 55762306a36Sopenharmony_ci int ret; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci if (!test_bit(QM_SUPPORT_SVA_PREFETCH, &qm->caps)) 56062306a36Sopenharmony_ci return; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci /* Enable prefetch */ 56362306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + HPRE_PREFETCH_CFG); 56462306a36Sopenharmony_ci val &= HPRE_PREFETCH_ENABLE; 56562306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_PREFETCH_CFG); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci ret = readl_relaxed_poll_timeout(qm->io_base + HPRE_PREFETCH_CFG, 56862306a36Sopenharmony_ci val, !(val & HPRE_PREFETCH_DISABLE), 56962306a36Sopenharmony_ci HPRE_REG_RD_INTVRL_US, 57062306a36Sopenharmony_ci HPRE_REG_RD_TMOUT_US); 57162306a36Sopenharmony_ci if (ret) 57262306a36Sopenharmony_ci pci_err(qm->pdev, "failed to open sva prefetch\n"); 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic void hpre_close_sva_prefetch(struct hisi_qm *qm) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci u32 val; 57862306a36Sopenharmony_ci int ret; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci if (!test_bit(QM_SUPPORT_SVA_PREFETCH, &qm->caps)) 58162306a36Sopenharmony_ci return; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + HPRE_PREFETCH_CFG); 58462306a36Sopenharmony_ci val |= HPRE_PREFETCH_DISABLE; 58562306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_PREFETCH_CFG); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci ret = readl_relaxed_poll_timeout(qm->io_base + HPRE_SVA_PREFTCH_DFX, 58862306a36Sopenharmony_ci val, !(val & HPRE_SVA_DISABLE_READY), 58962306a36Sopenharmony_ci HPRE_REG_RD_INTVRL_US, 59062306a36Sopenharmony_ci HPRE_REG_RD_TMOUT_US); 59162306a36Sopenharmony_ci if (ret) 59262306a36Sopenharmony_ci pci_err(qm->pdev, "failed to close sva prefetch\n"); 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cistatic void hpre_enable_clock_gate(struct hisi_qm *qm) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci u32 val; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci if (qm->ver < QM_HW_V3) 60062306a36Sopenharmony_ci return; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci val = readl(qm->io_base + HPRE_CLKGATE_CTL); 60362306a36Sopenharmony_ci val |= HPRE_CLKGATE_CTL_EN; 60462306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_CLKGATE_CTL); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci val = readl(qm->io_base + HPRE_PEH_CFG_AUTO_GATE); 60762306a36Sopenharmony_ci val |= HPRE_PEH_CFG_AUTO_GATE_EN; 60862306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci val = readl(qm->io_base + HPRE_CLUSTER_DYN_CTL); 61162306a36Sopenharmony_ci val |= HPRE_CLUSTER_DYN_CTL_EN; 61262306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_CLUSTER_DYN_CTL); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + HPRE_CORE_SHB_CFG); 61562306a36Sopenharmony_ci val |= HPRE_CORE_GATE_EN; 61662306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_CORE_SHB_CFG); 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_cistatic void hpre_disable_clock_gate(struct hisi_qm *qm) 62062306a36Sopenharmony_ci{ 62162306a36Sopenharmony_ci u32 val; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if (qm->ver < QM_HW_V3) 62462306a36Sopenharmony_ci return; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci val = readl(qm->io_base + HPRE_CLKGATE_CTL); 62762306a36Sopenharmony_ci val &= ~HPRE_CLKGATE_CTL_EN; 62862306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_CLKGATE_CTL); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci val = readl(qm->io_base + HPRE_PEH_CFG_AUTO_GATE); 63162306a36Sopenharmony_ci val &= ~HPRE_PEH_CFG_AUTO_GATE_EN; 63262306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci val = readl(qm->io_base + HPRE_CLUSTER_DYN_CTL); 63562306a36Sopenharmony_ci val &= ~HPRE_CLUSTER_DYN_CTL_EN; 63662306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_CLUSTER_DYN_CTL); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + HPRE_CORE_SHB_CFG); 63962306a36Sopenharmony_ci val &= ~HPRE_CORE_GATE_EN; 64062306a36Sopenharmony_ci writel(val, qm->io_base + HPRE_CORE_SHB_CFG); 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic int hpre_set_user_domain_and_cache(struct hisi_qm *qm) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 64662306a36Sopenharmony_ci u32 val; 64762306a36Sopenharmony_ci int ret; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci /* disabel dynamic clock gate before sram init */ 65062306a36Sopenharmony_ci hpre_disable_clock_gate(qm); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci writel(HPRE_QM_USR_CFG_MASK, qm->io_base + QM_ARUSER_M_CFG_ENABLE); 65362306a36Sopenharmony_ci writel(HPRE_QM_USR_CFG_MASK, qm->io_base + QM_AWUSER_M_CFG_ENABLE); 65462306a36Sopenharmony_ci writel_relaxed(HPRE_QM_AXI_CFG_MASK, qm->io_base + QM_AXI_M_CFG); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci /* HPRE need more time, we close this interrupt */ 65762306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + HPRE_QM_ABNML_INT_MASK); 65862306a36Sopenharmony_ci val |= BIT(HPRE_TIMEOUT_ABNML_BIT); 65962306a36Sopenharmony_ci writel_relaxed(val, qm->io_base + HPRE_QM_ABNML_INT_MASK); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci if (qm->ver >= QM_HW_V3) 66262306a36Sopenharmony_ci writel(HPRE_RSA_ENB | HPRE_ECC_ENB, 66362306a36Sopenharmony_ci qm->io_base + HPRE_TYPES_ENB); 66462306a36Sopenharmony_ci else 66562306a36Sopenharmony_ci writel(HPRE_RSA_ENB, qm->io_base + HPRE_TYPES_ENB); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci writel(HPRE_QM_VFG_AX_MASK, qm->io_base + HPRE_VFG_AXCACHE); 66862306a36Sopenharmony_ci writel(0x0, qm->io_base + HPRE_BD_ENDIAN); 66962306a36Sopenharmony_ci writel(0x0, qm->io_base + HPRE_INT_MASK); 67062306a36Sopenharmony_ci writel(0x0, qm->io_base + HPRE_POISON_BYPASS); 67162306a36Sopenharmony_ci writel(0x0, qm->io_base + HPRE_COMM_CNT_CLR_CE); 67262306a36Sopenharmony_ci writel(0x0, qm->io_base + HPRE_ECC_BYPASS); 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci writel(HPRE_BD_USR_MASK, qm->io_base + HPRE_BD_ARUSR_CFG); 67562306a36Sopenharmony_ci writel(HPRE_BD_USR_MASK, qm->io_base + HPRE_BD_AWUSR_CFG); 67662306a36Sopenharmony_ci writel(0x1, qm->io_base + HPRE_RDCHN_INI_CFG); 67762306a36Sopenharmony_ci ret = readl_relaxed_poll_timeout(qm->io_base + HPRE_RDCHN_INI_ST, val, 67862306a36Sopenharmony_ci val & BIT(0), 67962306a36Sopenharmony_ci HPRE_REG_RD_INTVRL_US, 68062306a36Sopenharmony_ci HPRE_REG_RD_TMOUT_US); 68162306a36Sopenharmony_ci if (ret) { 68262306a36Sopenharmony_ci dev_err(dev, "read rd channel timeout fail!\n"); 68362306a36Sopenharmony_ci return -ETIMEDOUT; 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci ret = hpre_set_cluster(qm); 68762306a36Sopenharmony_ci if (ret) 68862306a36Sopenharmony_ci return -ETIMEDOUT; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* This setting is only needed by Kunpeng 920. */ 69162306a36Sopenharmony_ci if (qm->ver == QM_HW_V2) { 69262306a36Sopenharmony_ci ret = hpre_cfg_by_dsm(qm); 69362306a36Sopenharmony_ci if (ret) 69462306a36Sopenharmony_ci return ret; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci disable_flr_of_bme(qm); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci /* Config data buffer pasid needed by Kunpeng 920 */ 70062306a36Sopenharmony_ci hpre_config_pasid(qm); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci hpre_enable_clock_gate(qm); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci return ret; 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic void hpre_cnt_regs_clear(struct hisi_qm *qm) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci unsigned long offset; 71062306a36Sopenharmony_ci u8 clusters_num; 71162306a36Sopenharmony_ci int i; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /* clear clusterX/cluster_ctrl */ 71462306a36Sopenharmony_ci clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val; 71562306a36Sopenharmony_ci for (i = 0; i < clusters_num; i++) { 71662306a36Sopenharmony_ci offset = HPRE_CLSTR_BASE + i * HPRE_CLSTR_ADDR_INTRVL; 71762306a36Sopenharmony_ci writel(0x0, qm->io_base + offset + HPRE_CLUSTER_INQURY); 71862306a36Sopenharmony_ci } 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci /* clear rdclr_en */ 72162306a36Sopenharmony_ci writel(0x0, qm->io_base + HPRE_CTRL_CNT_CLR_CE); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci hisi_qm_debug_regs_clear(qm); 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cistatic void hpre_master_ooo_ctrl(struct hisi_qm *qm, bool enable) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci u32 val1, val2; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci val1 = readl(qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB); 73162306a36Sopenharmony_ci if (enable) { 73262306a36Sopenharmony_ci val1 |= HPRE_AM_OOO_SHUTDOWN_ENABLE; 73362306a36Sopenharmony_ci val2 = hisi_qm_get_hw_info(qm, hpre_basic_info, 73462306a36Sopenharmony_ci HPRE_OOO_SHUTDOWN_MASK_CAP, qm->cap_ver); 73562306a36Sopenharmony_ci } else { 73662306a36Sopenharmony_ci val1 &= ~HPRE_AM_OOO_SHUTDOWN_ENABLE; 73762306a36Sopenharmony_ci val2 = 0x0; 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci if (qm->ver > QM_HW_V2) 74162306a36Sopenharmony_ci writel(val2, qm->io_base + HPRE_OOO_SHUTDOWN_SEL); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci writel(val1, qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB); 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_cistatic void hpre_hw_error_disable(struct hisi_qm *qm) 74762306a36Sopenharmony_ci{ 74862306a36Sopenharmony_ci u32 ce, nfe; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci ce = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_CE_MASK_CAP, qm->cap_ver); 75162306a36Sopenharmony_ci nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci /* disable hpre hw error interrupts */ 75462306a36Sopenharmony_ci writel(ce | nfe | HPRE_HAC_RAS_FE_ENABLE, qm->io_base + HPRE_INT_MASK); 75562306a36Sopenharmony_ci /* disable HPRE block master OOO when nfe occurs on Kunpeng930 */ 75662306a36Sopenharmony_ci hpre_master_ooo_ctrl(qm, false); 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_cistatic void hpre_hw_error_enable(struct hisi_qm *qm) 76062306a36Sopenharmony_ci{ 76162306a36Sopenharmony_ci u32 ce, nfe; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci ce = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_CE_MASK_CAP, qm->cap_ver); 76462306a36Sopenharmony_ci nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci /* clear HPRE hw error source if having */ 76762306a36Sopenharmony_ci writel(ce | nfe | HPRE_HAC_RAS_FE_ENABLE, qm->io_base + HPRE_HAC_SOURCE_INT); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci /* configure error type */ 77062306a36Sopenharmony_ci writel(ce, qm->io_base + HPRE_RAS_CE_ENB); 77162306a36Sopenharmony_ci writel(nfe, qm->io_base + HPRE_RAS_NFE_ENB); 77262306a36Sopenharmony_ci writel(HPRE_HAC_RAS_FE_ENABLE, qm->io_base + HPRE_RAS_FE_ENB); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci /* enable HPRE block master OOO when nfe occurs on Kunpeng930 */ 77562306a36Sopenharmony_ci hpre_master_ooo_ctrl(qm, true); 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* enable hpre hw error interrupts */ 77862306a36Sopenharmony_ci writel(HPRE_CORE_INT_ENABLE, qm->io_base + HPRE_INT_MASK); 77962306a36Sopenharmony_ci} 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_cistatic inline struct hisi_qm *hpre_file_to_qm(struct hpre_debugfs_file *file) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci struct hpre *hpre = container_of(file->debug, struct hpre, debug); 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci return &hpre->qm; 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_cistatic u32 hpre_clear_enable_read(struct hpre_debugfs_file *file) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci struct hisi_qm *qm = hpre_file_to_qm(file); 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci return readl(qm->io_base + HPRE_CTRL_CNT_CLR_CE) & 79362306a36Sopenharmony_ci HPRE_CTRL_CNT_CLR_CE_BIT; 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cistatic int hpre_clear_enable_write(struct hpre_debugfs_file *file, u32 val) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci struct hisi_qm *qm = hpre_file_to_qm(file); 79962306a36Sopenharmony_ci u32 tmp; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (val != 1 && val != 0) 80262306a36Sopenharmony_ci return -EINVAL; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci tmp = (readl(qm->io_base + HPRE_CTRL_CNT_CLR_CE) & 80562306a36Sopenharmony_ci ~HPRE_CTRL_CNT_CLR_CE_BIT) | val; 80662306a36Sopenharmony_ci writel(tmp, qm->io_base + HPRE_CTRL_CNT_CLR_CE); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci} 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_cistatic u32 hpre_cluster_inqry_read(struct hpre_debugfs_file *file) 81262306a36Sopenharmony_ci{ 81362306a36Sopenharmony_ci struct hisi_qm *qm = hpre_file_to_qm(file); 81462306a36Sopenharmony_ci int cluster_index = file->index - HPRE_CLUSTER_CTRL; 81562306a36Sopenharmony_ci unsigned long offset = HPRE_CLSTR_BASE + 81662306a36Sopenharmony_ci cluster_index * HPRE_CLSTR_ADDR_INTRVL; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci return readl(qm->io_base + offset + HPRE_CLSTR_ADDR_INQRY_RSLT); 81962306a36Sopenharmony_ci} 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_cistatic void hpre_cluster_inqry_write(struct hpre_debugfs_file *file, u32 val) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci struct hisi_qm *qm = hpre_file_to_qm(file); 82462306a36Sopenharmony_ci int cluster_index = file->index - HPRE_CLUSTER_CTRL; 82562306a36Sopenharmony_ci unsigned long offset = HPRE_CLSTR_BASE + cluster_index * 82662306a36Sopenharmony_ci HPRE_CLSTR_ADDR_INTRVL; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci writel(val, qm->io_base + offset + HPRE_CLUSTER_INQURY); 82962306a36Sopenharmony_ci} 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_cistatic ssize_t hpre_ctrl_debug_read(struct file *filp, char __user *buf, 83262306a36Sopenharmony_ci size_t count, loff_t *pos) 83362306a36Sopenharmony_ci{ 83462306a36Sopenharmony_ci struct hpre_debugfs_file *file = filp->private_data; 83562306a36Sopenharmony_ci struct hisi_qm *qm = hpre_file_to_qm(file); 83662306a36Sopenharmony_ci char tbuf[HPRE_DBGFS_VAL_MAX_LEN]; 83762306a36Sopenharmony_ci u32 val; 83862306a36Sopenharmony_ci int ret; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci ret = hisi_qm_get_dfx_access(qm); 84162306a36Sopenharmony_ci if (ret) 84262306a36Sopenharmony_ci return ret; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci spin_lock_irq(&file->lock); 84562306a36Sopenharmony_ci switch (file->type) { 84662306a36Sopenharmony_ci case HPRE_CLEAR_ENABLE: 84762306a36Sopenharmony_ci val = hpre_clear_enable_read(file); 84862306a36Sopenharmony_ci break; 84962306a36Sopenharmony_ci case HPRE_CLUSTER_CTRL: 85062306a36Sopenharmony_ci val = hpre_cluster_inqry_read(file); 85162306a36Sopenharmony_ci break; 85262306a36Sopenharmony_ci default: 85362306a36Sopenharmony_ci goto err_input; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci spin_unlock_irq(&file->lock); 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci hisi_qm_put_dfx_access(qm); 85862306a36Sopenharmony_ci ret = snprintf(tbuf, HPRE_DBGFS_VAL_MAX_LEN, "%u\n", val); 85962306a36Sopenharmony_ci return simple_read_from_buffer(buf, count, pos, tbuf, ret); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_cierr_input: 86262306a36Sopenharmony_ci spin_unlock_irq(&file->lock); 86362306a36Sopenharmony_ci hisi_qm_put_dfx_access(qm); 86462306a36Sopenharmony_ci return -EINVAL; 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_cistatic ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf, 86862306a36Sopenharmony_ci size_t count, loff_t *pos) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci struct hpre_debugfs_file *file = filp->private_data; 87162306a36Sopenharmony_ci struct hisi_qm *qm = hpre_file_to_qm(file); 87262306a36Sopenharmony_ci char tbuf[HPRE_DBGFS_VAL_MAX_LEN]; 87362306a36Sopenharmony_ci unsigned long val; 87462306a36Sopenharmony_ci int len, ret; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci if (*pos != 0) 87762306a36Sopenharmony_ci return 0; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci if (count >= HPRE_DBGFS_VAL_MAX_LEN) 88062306a36Sopenharmony_ci return -ENOSPC; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci len = simple_write_to_buffer(tbuf, HPRE_DBGFS_VAL_MAX_LEN - 1, 88362306a36Sopenharmony_ci pos, buf, count); 88462306a36Sopenharmony_ci if (len < 0) 88562306a36Sopenharmony_ci return len; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci tbuf[len] = '\0'; 88862306a36Sopenharmony_ci if (kstrtoul(tbuf, 0, &val)) 88962306a36Sopenharmony_ci return -EFAULT; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci ret = hisi_qm_get_dfx_access(qm); 89262306a36Sopenharmony_ci if (ret) 89362306a36Sopenharmony_ci return ret; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci spin_lock_irq(&file->lock); 89662306a36Sopenharmony_ci switch (file->type) { 89762306a36Sopenharmony_ci case HPRE_CLEAR_ENABLE: 89862306a36Sopenharmony_ci ret = hpre_clear_enable_write(file, val); 89962306a36Sopenharmony_ci if (ret) 90062306a36Sopenharmony_ci goto err_input; 90162306a36Sopenharmony_ci break; 90262306a36Sopenharmony_ci case HPRE_CLUSTER_CTRL: 90362306a36Sopenharmony_ci hpre_cluster_inqry_write(file, val); 90462306a36Sopenharmony_ci break; 90562306a36Sopenharmony_ci default: 90662306a36Sopenharmony_ci ret = -EINVAL; 90762306a36Sopenharmony_ci goto err_input; 90862306a36Sopenharmony_ci } 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci ret = count; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_cierr_input: 91362306a36Sopenharmony_ci spin_unlock_irq(&file->lock); 91462306a36Sopenharmony_ci hisi_qm_put_dfx_access(qm); 91562306a36Sopenharmony_ci return ret; 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_cistatic const struct file_operations hpre_ctrl_debug_fops = { 91962306a36Sopenharmony_ci .owner = THIS_MODULE, 92062306a36Sopenharmony_ci .open = simple_open, 92162306a36Sopenharmony_ci .read = hpre_ctrl_debug_read, 92262306a36Sopenharmony_ci .write = hpre_ctrl_debug_write, 92362306a36Sopenharmony_ci}; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cistatic int hpre_debugfs_atomic64_get(void *data, u64 *val) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci struct hpre_dfx *dfx_item = data; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci *val = atomic64_read(&dfx_item->value); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci return 0; 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic int hpre_debugfs_atomic64_set(void *data, u64 val) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci struct hpre_dfx *dfx_item = data; 93762306a36Sopenharmony_ci struct hpre_dfx *hpre_dfx = NULL; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci if (dfx_item->type == HPRE_OVERTIME_THRHLD) { 94062306a36Sopenharmony_ci hpre_dfx = dfx_item - HPRE_OVERTIME_THRHLD; 94162306a36Sopenharmony_ci atomic64_set(&hpre_dfx[HPRE_OVER_THRHLD_CNT].value, 0); 94262306a36Sopenharmony_ci } else if (val) { 94362306a36Sopenharmony_ci return -EINVAL; 94462306a36Sopenharmony_ci } 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci atomic64_set(&dfx_item->value, val); 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci return 0; 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(hpre_atomic64_ops, hpre_debugfs_atomic64_get, 95262306a36Sopenharmony_ci hpre_debugfs_atomic64_set, "%llu\n"); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_cistatic int hpre_create_debugfs_file(struct hisi_qm *qm, struct dentry *dir, 95562306a36Sopenharmony_ci enum hpre_ctrl_dbgfs_file type, int indx) 95662306a36Sopenharmony_ci{ 95762306a36Sopenharmony_ci struct hpre *hpre = container_of(qm, struct hpre, qm); 95862306a36Sopenharmony_ci struct hpre_debug *dbg = &hpre->debug; 95962306a36Sopenharmony_ci struct dentry *file_dir; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci if (dir) 96262306a36Sopenharmony_ci file_dir = dir; 96362306a36Sopenharmony_ci else 96462306a36Sopenharmony_ci file_dir = qm->debug.debug_root; 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci if (type >= HPRE_DEBUG_FILE_NUM) 96762306a36Sopenharmony_ci return -EINVAL; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci spin_lock_init(&dbg->files[indx].lock); 97062306a36Sopenharmony_ci dbg->files[indx].debug = dbg; 97162306a36Sopenharmony_ci dbg->files[indx].type = type; 97262306a36Sopenharmony_ci dbg->files[indx].index = indx; 97362306a36Sopenharmony_ci debugfs_create_file(hpre_debug_file_name[type], 0600, file_dir, 97462306a36Sopenharmony_ci dbg->files + indx, &hpre_ctrl_debug_fops); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci return 0; 97762306a36Sopenharmony_ci} 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_cistatic int hpre_pf_comm_regs_debugfs_init(struct hisi_qm *qm) 98062306a36Sopenharmony_ci{ 98162306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 98262306a36Sopenharmony_ci struct debugfs_regset32 *regset; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); 98562306a36Sopenharmony_ci if (!regset) 98662306a36Sopenharmony_ci return -ENOMEM; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci regset->regs = hpre_com_dfx_regs; 98962306a36Sopenharmony_ci regset->nregs = ARRAY_SIZE(hpre_com_dfx_regs); 99062306a36Sopenharmony_ci regset->base = qm->io_base; 99162306a36Sopenharmony_ci regset->dev = dev; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci debugfs_create_file("regs", 0444, qm->debug.debug_root, 99462306a36Sopenharmony_ci regset, &hpre_com_regs_fops); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci return 0; 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_cistatic int hpre_cluster_debugfs_init(struct hisi_qm *qm) 100062306a36Sopenharmony_ci{ 100162306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 100262306a36Sopenharmony_ci char buf[HPRE_DBGFS_VAL_MAX_LEN]; 100362306a36Sopenharmony_ci struct debugfs_regset32 *regset; 100462306a36Sopenharmony_ci struct dentry *tmp_d; 100562306a36Sopenharmony_ci u8 clusters_num; 100662306a36Sopenharmony_ci int i, ret; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val; 100962306a36Sopenharmony_ci for (i = 0; i < clusters_num; i++) { 101062306a36Sopenharmony_ci ret = snprintf(buf, HPRE_DBGFS_VAL_MAX_LEN, "cluster%d", i); 101162306a36Sopenharmony_ci if (ret >= HPRE_DBGFS_VAL_MAX_LEN) 101262306a36Sopenharmony_ci return -EINVAL; 101362306a36Sopenharmony_ci tmp_d = debugfs_create_dir(buf, qm->debug.debug_root); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); 101662306a36Sopenharmony_ci if (!regset) 101762306a36Sopenharmony_ci return -ENOMEM; 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci regset->regs = hpre_cluster_dfx_regs; 102062306a36Sopenharmony_ci regset->nregs = ARRAY_SIZE(hpre_cluster_dfx_regs); 102162306a36Sopenharmony_ci regset->base = qm->io_base + hpre_cluster_offsets[i]; 102262306a36Sopenharmony_ci regset->dev = dev; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci debugfs_create_file("regs", 0444, tmp_d, regset, 102562306a36Sopenharmony_ci &hpre_cluster_regs_fops); 102662306a36Sopenharmony_ci ret = hpre_create_debugfs_file(qm, tmp_d, HPRE_CLUSTER_CTRL, 102762306a36Sopenharmony_ci i + HPRE_CLUSTER_CTRL); 102862306a36Sopenharmony_ci if (ret) 102962306a36Sopenharmony_ci return ret; 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci return 0; 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_cistatic int hpre_ctrl_debug_init(struct hisi_qm *qm) 103662306a36Sopenharmony_ci{ 103762306a36Sopenharmony_ci int ret; 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci ret = hpre_create_debugfs_file(qm, NULL, HPRE_CLEAR_ENABLE, 104062306a36Sopenharmony_ci HPRE_CLEAR_ENABLE); 104162306a36Sopenharmony_ci if (ret) 104262306a36Sopenharmony_ci return ret; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci ret = hpre_pf_comm_regs_debugfs_init(qm); 104562306a36Sopenharmony_ci if (ret) 104662306a36Sopenharmony_ci return ret; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci return hpre_cluster_debugfs_init(qm); 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_cistatic void hpre_dfx_debug_init(struct hisi_qm *qm) 105262306a36Sopenharmony_ci{ 105362306a36Sopenharmony_ci struct dfx_diff_registers *hpre_regs = qm->debug.acc_diff_regs; 105462306a36Sopenharmony_ci struct hpre *hpre = container_of(qm, struct hpre, qm); 105562306a36Sopenharmony_ci struct hpre_dfx *dfx = hpre->debug.dfx; 105662306a36Sopenharmony_ci struct dentry *parent; 105762306a36Sopenharmony_ci int i; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci parent = debugfs_create_dir("hpre_dfx", qm->debug.debug_root); 106062306a36Sopenharmony_ci for (i = 0; i < HPRE_DFX_FILE_NUM; i++) { 106162306a36Sopenharmony_ci dfx[i].type = i; 106262306a36Sopenharmony_ci debugfs_create_file(hpre_dfx_files[i], 0644, parent, &dfx[i], 106362306a36Sopenharmony_ci &hpre_atomic64_ops); 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF && hpre_regs) 106762306a36Sopenharmony_ci debugfs_create_file("diff_regs", 0444, parent, 106862306a36Sopenharmony_ci qm, &hpre_diff_regs_fops); 106962306a36Sopenharmony_ci} 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_cistatic int hpre_debugfs_init(struct hisi_qm *qm) 107262306a36Sopenharmony_ci{ 107362306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 107462306a36Sopenharmony_ci int ret; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci qm->debug.debug_root = debugfs_create_dir(dev_name(dev), 107762306a36Sopenharmony_ci hpre_debugfs_root); 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci qm->debug.sqe_mask_offset = HPRE_SQE_MASK_OFFSET; 108062306a36Sopenharmony_ci qm->debug.sqe_mask_len = HPRE_SQE_MASK_LEN; 108162306a36Sopenharmony_ci ret = hisi_qm_regs_debugfs_init(qm, hpre_diff_regs, ARRAY_SIZE(hpre_diff_regs)); 108262306a36Sopenharmony_ci if (ret) { 108362306a36Sopenharmony_ci dev_warn(dev, "Failed to init HPRE diff regs!\n"); 108462306a36Sopenharmony_ci goto debugfs_remove; 108562306a36Sopenharmony_ci } 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci hisi_qm_debug_init(qm); 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci if (qm->pdev->device == PCI_DEVICE_ID_HUAWEI_HPRE_PF) { 109062306a36Sopenharmony_ci ret = hpre_ctrl_debug_init(qm); 109162306a36Sopenharmony_ci if (ret) 109262306a36Sopenharmony_ci goto failed_to_create; 109362306a36Sopenharmony_ci } 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci hpre_dfx_debug_init(qm); 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci return 0; 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_cifailed_to_create: 110062306a36Sopenharmony_ci hisi_qm_regs_debugfs_uninit(qm, ARRAY_SIZE(hpre_diff_regs)); 110162306a36Sopenharmony_cidebugfs_remove: 110262306a36Sopenharmony_ci debugfs_remove_recursive(qm->debug.debug_root); 110362306a36Sopenharmony_ci return ret; 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic void hpre_debugfs_exit(struct hisi_qm *qm) 110762306a36Sopenharmony_ci{ 110862306a36Sopenharmony_ci hisi_qm_regs_debugfs_uninit(qm, ARRAY_SIZE(hpre_diff_regs)); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci debugfs_remove_recursive(qm->debug.debug_root); 111162306a36Sopenharmony_ci} 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_cistatic int hpre_pre_store_cap_reg(struct hisi_qm *qm) 111462306a36Sopenharmony_ci{ 111562306a36Sopenharmony_ci struct hisi_qm_cap_record *hpre_cap; 111662306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 111762306a36Sopenharmony_ci size_t i, size; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci size = ARRAY_SIZE(hpre_pre_store_caps); 112062306a36Sopenharmony_ci hpre_cap = devm_kzalloc(dev, sizeof(*hpre_cap) * size, GFP_KERNEL); 112162306a36Sopenharmony_ci if (!hpre_cap) 112262306a36Sopenharmony_ci return -ENOMEM; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci for (i = 0; i < size; i++) { 112562306a36Sopenharmony_ci hpre_cap[i].type = hpre_pre_store_caps[i]; 112662306a36Sopenharmony_ci hpre_cap[i].cap_val = hisi_qm_get_hw_info(qm, hpre_basic_info, 112762306a36Sopenharmony_ci hpre_pre_store_caps[i], qm->cap_ver); 112862306a36Sopenharmony_ci } 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci if (hpre_cap[HPRE_CLUSTER_NUM_CAP_IDX].cap_val > HPRE_CLUSTERS_NUM_MAX) { 113162306a36Sopenharmony_ci dev_err(dev, "Device cluster num %u is out of range for driver supports %d!\n", 113262306a36Sopenharmony_ci hpre_cap[HPRE_CLUSTER_NUM_CAP_IDX].cap_val, HPRE_CLUSTERS_NUM_MAX); 113362306a36Sopenharmony_ci return -EINVAL; 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci qm->cap_tables.dev_cap_table = hpre_cap; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci return 0; 113962306a36Sopenharmony_ci} 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_cistatic int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) 114262306a36Sopenharmony_ci{ 114362306a36Sopenharmony_ci u64 alg_msk; 114462306a36Sopenharmony_ci int ret; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci if (pdev->revision == QM_HW_V1) { 114762306a36Sopenharmony_ci pci_warn(pdev, "HPRE version 1 is not supported!\n"); 114862306a36Sopenharmony_ci return -EINVAL; 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci qm->mode = uacce_mode; 115262306a36Sopenharmony_ci qm->pdev = pdev; 115362306a36Sopenharmony_ci qm->ver = pdev->revision; 115462306a36Sopenharmony_ci qm->sqe_size = HPRE_SQE_SIZE; 115562306a36Sopenharmony_ci qm->dev_name = hpre_name; 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci qm->fun_type = (pdev->device == PCI_DEVICE_ID_HUAWEI_HPRE_PF) ? 115862306a36Sopenharmony_ci QM_HW_PF : QM_HW_VF; 115962306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF) { 116062306a36Sopenharmony_ci qm->qp_base = HPRE_PF_DEF_Q_BASE; 116162306a36Sopenharmony_ci qm->qp_num = pf_q_num; 116262306a36Sopenharmony_ci qm->debug.curr_qm_qp_num = pf_q_num; 116362306a36Sopenharmony_ci qm->qm_list = &hpre_devices; 116462306a36Sopenharmony_ci if (pf_q_num_flag) 116562306a36Sopenharmony_ci set_bit(QM_MODULE_PARAM, &qm->misc_ctl); 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci ret = hisi_qm_init(qm); 116962306a36Sopenharmony_ci if (ret) { 117062306a36Sopenharmony_ci pci_err(pdev, "Failed to init hpre qm configures!\n"); 117162306a36Sopenharmony_ci return ret; 117262306a36Sopenharmony_ci } 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci /* Fetch and save the value of capability registers */ 117562306a36Sopenharmony_ci ret = hpre_pre_store_cap_reg(qm); 117662306a36Sopenharmony_ci if (ret) { 117762306a36Sopenharmony_ci pci_err(pdev, "Failed to pre-store capability registers!\n"); 117862306a36Sopenharmony_ci hisi_qm_uninit(qm); 117962306a36Sopenharmony_ci return ret; 118062306a36Sopenharmony_ci } 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci alg_msk = qm->cap_tables.dev_cap_table[HPRE_DEV_ALG_BITMAP_CAP_IDX].cap_val; 118362306a36Sopenharmony_ci ret = hisi_qm_set_algs(qm, alg_msk, hpre_dev_algs, ARRAY_SIZE(hpre_dev_algs)); 118462306a36Sopenharmony_ci if (ret) { 118562306a36Sopenharmony_ci pci_err(pdev, "Failed to set hpre algs!\n"); 118662306a36Sopenharmony_ci hisi_qm_uninit(qm); 118762306a36Sopenharmony_ci } 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci return ret; 119062306a36Sopenharmony_ci} 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_cistatic int hpre_show_last_regs_init(struct hisi_qm *qm) 119362306a36Sopenharmony_ci{ 119462306a36Sopenharmony_ci int cluster_dfx_regs_num = ARRAY_SIZE(hpre_cluster_dfx_regs); 119562306a36Sopenharmony_ci int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs); 119662306a36Sopenharmony_ci struct qm_debug *debug = &qm->debug; 119762306a36Sopenharmony_ci void __iomem *io_base; 119862306a36Sopenharmony_ci u8 clusters_num; 119962306a36Sopenharmony_ci int i, j, idx; 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val; 120262306a36Sopenharmony_ci debug->last_words = kcalloc(cluster_dfx_regs_num * clusters_num + 120362306a36Sopenharmony_ci com_dfx_regs_num, sizeof(unsigned int), GFP_KERNEL); 120462306a36Sopenharmony_ci if (!debug->last_words) 120562306a36Sopenharmony_ci return -ENOMEM; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci for (i = 0; i < com_dfx_regs_num; i++) 120862306a36Sopenharmony_ci debug->last_words[i] = readl_relaxed(qm->io_base + 120962306a36Sopenharmony_ci hpre_com_dfx_regs[i].offset); 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci for (i = 0; i < clusters_num; i++) { 121262306a36Sopenharmony_ci io_base = qm->io_base + hpre_cluster_offsets[i]; 121362306a36Sopenharmony_ci for (j = 0; j < cluster_dfx_regs_num; j++) { 121462306a36Sopenharmony_ci idx = com_dfx_regs_num + i * cluster_dfx_regs_num + j; 121562306a36Sopenharmony_ci debug->last_words[idx] = readl_relaxed( 121662306a36Sopenharmony_ci io_base + hpre_cluster_dfx_regs[j].offset); 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci } 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci return 0; 122162306a36Sopenharmony_ci} 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_cistatic void hpre_show_last_regs_uninit(struct hisi_qm *qm) 122462306a36Sopenharmony_ci{ 122562306a36Sopenharmony_ci struct qm_debug *debug = &qm->debug; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci if (qm->fun_type == QM_HW_VF || !debug->last_words) 122862306a36Sopenharmony_ci return; 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci kfree(debug->last_words); 123162306a36Sopenharmony_ci debug->last_words = NULL; 123262306a36Sopenharmony_ci} 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_cistatic void hpre_show_last_dfx_regs(struct hisi_qm *qm) 123562306a36Sopenharmony_ci{ 123662306a36Sopenharmony_ci int cluster_dfx_regs_num = ARRAY_SIZE(hpre_cluster_dfx_regs); 123762306a36Sopenharmony_ci int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs); 123862306a36Sopenharmony_ci struct qm_debug *debug = &qm->debug; 123962306a36Sopenharmony_ci struct pci_dev *pdev = qm->pdev; 124062306a36Sopenharmony_ci void __iomem *io_base; 124162306a36Sopenharmony_ci u8 clusters_num; 124262306a36Sopenharmony_ci int i, j, idx; 124362306a36Sopenharmony_ci u32 val; 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci if (qm->fun_type == QM_HW_VF || !debug->last_words) 124662306a36Sopenharmony_ci return; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci /* dumps last word of the debugging registers during controller reset */ 124962306a36Sopenharmony_ci for (i = 0; i < com_dfx_regs_num; i++) { 125062306a36Sopenharmony_ci val = readl_relaxed(qm->io_base + hpre_com_dfx_regs[i].offset); 125162306a36Sopenharmony_ci if (debug->last_words[i] != val) 125262306a36Sopenharmony_ci pci_info(pdev, "Common_core:%s \t= 0x%08x => 0x%08x\n", 125362306a36Sopenharmony_ci hpre_com_dfx_regs[i].name, debug->last_words[i], val); 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val; 125762306a36Sopenharmony_ci for (i = 0; i < clusters_num; i++) { 125862306a36Sopenharmony_ci io_base = qm->io_base + hpre_cluster_offsets[i]; 125962306a36Sopenharmony_ci for (j = 0; j < cluster_dfx_regs_num; j++) { 126062306a36Sopenharmony_ci val = readl_relaxed(io_base + 126162306a36Sopenharmony_ci hpre_cluster_dfx_regs[j].offset); 126262306a36Sopenharmony_ci idx = com_dfx_regs_num + i * cluster_dfx_regs_num + j; 126362306a36Sopenharmony_ci if (debug->last_words[idx] != val) 126462306a36Sopenharmony_ci pci_info(pdev, "cluster-%d:%s \t= 0x%08x => 0x%08x\n", 126562306a36Sopenharmony_ci i, hpre_cluster_dfx_regs[j].name, debug->last_words[idx], val); 126662306a36Sopenharmony_ci } 126762306a36Sopenharmony_ci } 126862306a36Sopenharmony_ci} 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_cistatic void hpre_log_hw_error(struct hisi_qm *qm, u32 err_sts) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci const struct hpre_hw_error *err = hpre_hw_errors; 127362306a36Sopenharmony_ci struct device *dev = &qm->pdev->dev; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci while (err->msg) { 127662306a36Sopenharmony_ci if (err->int_msk & err_sts) 127762306a36Sopenharmony_ci dev_warn(dev, "%s [error status=0x%x] found\n", 127862306a36Sopenharmony_ci err->msg, err->int_msk); 127962306a36Sopenharmony_ci err++; 128062306a36Sopenharmony_ci } 128162306a36Sopenharmony_ci} 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_cistatic u32 hpre_get_hw_err_status(struct hisi_qm *qm) 128462306a36Sopenharmony_ci{ 128562306a36Sopenharmony_ci return readl(qm->io_base + HPRE_INT_STATUS); 128662306a36Sopenharmony_ci} 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_cistatic void hpre_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) 128962306a36Sopenharmony_ci{ 129062306a36Sopenharmony_ci u32 nfe; 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci writel(err_sts, qm->io_base + HPRE_HAC_SOURCE_INT); 129362306a36Sopenharmony_ci nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); 129462306a36Sopenharmony_ci writel(nfe, qm->io_base + HPRE_RAS_NFE_ENB); 129562306a36Sopenharmony_ci} 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_cistatic void hpre_open_axi_master_ooo(struct hisi_qm *qm) 129862306a36Sopenharmony_ci{ 129962306a36Sopenharmony_ci u32 value; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci value = readl(qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB); 130262306a36Sopenharmony_ci writel(value & ~HPRE_AM_OOO_SHUTDOWN_ENABLE, 130362306a36Sopenharmony_ci qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB); 130462306a36Sopenharmony_ci writel(value | HPRE_AM_OOO_SHUTDOWN_ENABLE, 130562306a36Sopenharmony_ci qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB); 130662306a36Sopenharmony_ci} 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_cistatic void hpre_err_info_init(struct hisi_qm *qm) 130962306a36Sopenharmony_ci{ 131062306a36Sopenharmony_ci struct hisi_qm_err_info *err_info = &qm->err_info; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci err_info->fe = HPRE_HAC_RAS_FE_ENABLE; 131362306a36Sopenharmony_ci err_info->ce = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_QM_CE_MASK_CAP, qm->cap_ver); 131462306a36Sopenharmony_ci err_info->nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_QM_NFE_MASK_CAP, qm->cap_ver); 131562306a36Sopenharmony_ci err_info->ecc_2bits_mask = HPRE_CORE_ECC_2BIT_ERR | HPRE_OOO_ECC_2BIT_ERR; 131662306a36Sopenharmony_ci err_info->dev_shutdown_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, 131762306a36Sopenharmony_ci HPRE_OOO_SHUTDOWN_MASK_CAP, qm->cap_ver); 131862306a36Sopenharmony_ci err_info->qm_shutdown_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, 131962306a36Sopenharmony_ci HPRE_QM_OOO_SHUTDOWN_MASK_CAP, qm->cap_ver); 132062306a36Sopenharmony_ci err_info->qm_reset_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, 132162306a36Sopenharmony_ci HPRE_QM_RESET_MASK_CAP, qm->cap_ver); 132262306a36Sopenharmony_ci err_info->dev_reset_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, 132362306a36Sopenharmony_ci HPRE_RESET_MASK_CAP, qm->cap_ver); 132462306a36Sopenharmony_ci err_info->msi_wr_port = HPRE_WR_MSI_PORT; 132562306a36Sopenharmony_ci err_info->acpi_rst = "HRST"; 132662306a36Sopenharmony_ci} 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_cistatic const struct hisi_qm_err_ini hpre_err_ini = { 132962306a36Sopenharmony_ci .hw_init = hpre_set_user_domain_and_cache, 133062306a36Sopenharmony_ci .hw_err_enable = hpre_hw_error_enable, 133162306a36Sopenharmony_ci .hw_err_disable = hpre_hw_error_disable, 133262306a36Sopenharmony_ci .get_dev_hw_err_status = hpre_get_hw_err_status, 133362306a36Sopenharmony_ci .clear_dev_hw_err_status = hpre_clear_hw_err_status, 133462306a36Sopenharmony_ci .log_dev_hw_err = hpre_log_hw_error, 133562306a36Sopenharmony_ci .open_axi_master_ooo = hpre_open_axi_master_ooo, 133662306a36Sopenharmony_ci .open_sva_prefetch = hpre_open_sva_prefetch, 133762306a36Sopenharmony_ci .close_sva_prefetch = hpre_close_sva_prefetch, 133862306a36Sopenharmony_ci .show_last_dfx_regs = hpre_show_last_dfx_regs, 133962306a36Sopenharmony_ci .err_info_init = hpre_err_info_init, 134062306a36Sopenharmony_ci}; 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_cistatic int hpre_pf_probe_init(struct hpre *hpre) 134362306a36Sopenharmony_ci{ 134462306a36Sopenharmony_ci struct hisi_qm *qm = &hpre->qm; 134562306a36Sopenharmony_ci int ret; 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci ret = hpre_set_user_domain_and_cache(qm); 134862306a36Sopenharmony_ci if (ret) 134962306a36Sopenharmony_ci return ret; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci hpre_open_sva_prefetch(qm); 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci qm->err_ini = &hpre_err_ini; 135462306a36Sopenharmony_ci qm->err_ini->err_info_init(qm); 135562306a36Sopenharmony_ci hisi_qm_dev_err_init(qm); 135662306a36Sopenharmony_ci ret = hpre_show_last_regs_init(qm); 135762306a36Sopenharmony_ci if (ret) 135862306a36Sopenharmony_ci pci_err(qm->pdev, "Failed to init last word regs!\n"); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci return ret; 136162306a36Sopenharmony_ci} 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_cistatic int hpre_probe_init(struct hpre *hpre) 136462306a36Sopenharmony_ci{ 136562306a36Sopenharmony_ci u32 type_rate = HPRE_SHAPER_TYPE_RATE; 136662306a36Sopenharmony_ci struct hisi_qm *qm = &hpre->qm; 136762306a36Sopenharmony_ci int ret; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF) { 137062306a36Sopenharmony_ci ret = hpre_pf_probe_init(hpre); 137162306a36Sopenharmony_ci if (ret) 137262306a36Sopenharmony_ci return ret; 137362306a36Sopenharmony_ci /* Enable shaper type 0 */ 137462306a36Sopenharmony_ci if (qm->ver >= QM_HW_V3) { 137562306a36Sopenharmony_ci type_rate |= QM_SHAPER_ENABLE; 137662306a36Sopenharmony_ci qm->type_rate = type_rate; 137762306a36Sopenharmony_ci } 137862306a36Sopenharmony_ci } 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci return 0; 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_cistatic int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) 138462306a36Sopenharmony_ci{ 138562306a36Sopenharmony_ci struct hisi_qm *qm; 138662306a36Sopenharmony_ci struct hpre *hpre; 138762306a36Sopenharmony_ci int ret; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci hpre = devm_kzalloc(&pdev->dev, sizeof(*hpre), GFP_KERNEL); 139062306a36Sopenharmony_ci if (!hpre) 139162306a36Sopenharmony_ci return -ENOMEM; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci qm = &hpre->qm; 139462306a36Sopenharmony_ci ret = hpre_qm_init(qm, pdev); 139562306a36Sopenharmony_ci if (ret) { 139662306a36Sopenharmony_ci pci_err(pdev, "Failed to init HPRE QM (%d)!\n", ret); 139762306a36Sopenharmony_ci return ret; 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci ret = hpre_probe_init(hpre); 140162306a36Sopenharmony_ci if (ret) { 140262306a36Sopenharmony_ci pci_err(pdev, "Failed to probe (%d)!\n", ret); 140362306a36Sopenharmony_ci goto err_with_qm_init; 140462306a36Sopenharmony_ci } 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci ret = hisi_qm_start(qm); 140762306a36Sopenharmony_ci if (ret) 140862306a36Sopenharmony_ci goto err_with_err_init; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci ret = hpre_debugfs_init(qm); 141162306a36Sopenharmony_ci if (ret) 141262306a36Sopenharmony_ci dev_warn(&pdev->dev, "init debugfs fail!\n"); 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci ret = hisi_qm_alg_register(qm, &hpre_devices); 141562306a36Sopenharmony_ci if (ret < 0) { 141662306a36Sopenharmony_ci pci_err(pdev, "fail to register algs to crypto!\n"); 141762306a36Sopenharmony_ci goto err_with_qm_start; 141862306a36Sopenharmony_ci } 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci if (qm->uacce) { 142162306a36Sopenharmony_ci ret = uacce_register(qm->uacce); 142262306a36Sopenharmony_ci if (ret) { 142362306a36Sopenharmony_ci pci_err(pdev, "failed to register uacce (%d)!\n", ret); 142462306a36Sopenharmony_ci goto err_with_alg_register; 142562306a36Sopenharmony_ci } 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF && vfs_num) { 142962306a36Sopenharmony_ci ret = hisi_qm_sriov_enable(pdev, vfs_num); 143062306a36Sopenharmony_ci if (ret < 0) 143162306a36Sopenharmony_ci goto err_with_alg_register; 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci hisi_qm_pm_init(qm); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci return 0; 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_cierr_with_alg_register: 143962306a36Sopenharmony_ci hisi_qm_alg_unregister(qm, &hpre_devices); 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_cierr_with_qm_start: 144262306a36Sopenharmony_ci hpre_debugfs_exit(qm); 144362306a36Sopenharmony_ci hisi_qm_stop(qm, QM_NORMAL); 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_cierr_with_err_init: 144662306a36Sopenharmony_ci hpre_show_last_regs_uninit(qm); 144762306a36Sopenharmony_ci hisi_qm_dev_err_uninit(qm); 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_cierr_with_qm_init: 145062306a36Sopenharmony_ci hisi_qm_uninit(qm); 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci return ret; 145362306a36Sopenharmony_ci} 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_cistatic void hpre_remove(struct pci_dev *pdev) 145662306a36Sopenharmony_ci{ 145762306a36Sopenharmony_ci struct hisi_qm *qm = pci_get_drvdata(pdev); 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci hisi_qm_pm_uninit(qm); 146062306a36Sopenharmony_ci hisi_qm_wait_task_finish(qm, &hpre_devices); 146162306a36Sopenharmony_ci hisi_qm_alg_unregister(qm, &hpre_devices); 146262306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF && qm->vfs_num) 146362306a36Sopenharmony_ci hisi_qm_sriov_disable(pdev, true); 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci hpre_debugfs_exit(qm); 146662306a36Sopenharmony_ci hisi_qm_stop(qm, QM_NORMAL); 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci if (qm->fun_type == QM_HW_PF) { 146962306a36Sopenharmony_ci hpre_cnt_regs_clear(qm); 147062306a36Sopenharmony_ci qm->debug.curr_qm_qp_num = 0; 147162306a36Sopenharmony_ci hpre_show_last_regs_uninit(qm); 147262306a36Sopenharmony_ci hisi_qm_dev_err_uninit(qm); 147362306a36Sopenharmony_ci } 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci hisi_qm_uninit(qm); 147662306a36Sopenharmony_ci} 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_cistatic const struct dev_pm_ops hpre_pm_ops = { 147962306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(hisi_qm_suspend, hisi_qm_resume, NULL) 148062306a36Sopenharmony_ci}; 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_cistatic const struct pci_error_handlers hpre_err_handler = { 148362306a36Sopenharmony_ci .error_detected = hisi_qm_dev_err_detected, 148462306a36Sopenharmony_ci .slot_reset = hisi_qm_dev_slot_reset, 148562306a36Sopenharmony_ci .reset_prepare = hisi_qm_reset_prepare, 148662306a36Sopenharmony_ci .reset_done = hisi_qm_reset_done, 148762306a36Sopenharmony_ci}; 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_cistatic struct pci_driver hpre_pci_driver = { 149062306a36Sopenharmony_ci .name = hpre_name, 149162306a36Sopenharmony_ci .id_table = hpre_dev_ids, 149262306a36Sopenharmony_ci .probe = hpre_probe, 149362306a36Sopenharmony_ci .remove = hpre_remove, 149462306a36Sopenharmony_ci .sriov_configure = IS_ENABLED(CONFIG_PCI_IOV) ? 149562306a36Sopenharmony_ci hisi_qm_sriov_configure : NULL, 149662306a36Sopenharmony_ci .err_handler = &hpre_err_handler, 149762306a36Sopenharmony_ci .shutdown = hisi_qm_dev_shutdown, 149862306a36Sopenharmony_ci .driver.pm = &hpre_pm_ops, 149962306a36Sopenharmony_ci}; 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_cistruct pci_driver *hisi_hpre_get_pf_driver(void) 150262306a36Sopenharmony_ci{ 150362306a36Sopenharmony_ci return &hpre_pci_driver; 150462306a36Sopenharmony_ci} 150562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hisi_hpre_get_pf_driver); 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_cistatic void hpre_register_debugfs(void) 150862306a36Sopenharmony_ci{ 150962306a36Sopenharmony_ci if (!debugfs_initialized()) 151062306a36Sopenharmony_ci return; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci hpre_debugfs_root = debugfs_create_dir(hpre_name, NULL); 151362306a36Sopenharmony_ci} 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_cistatic void hpre_unregister_debugfs(void) 151662306a36Sopenharmony_ci{ 151762306a36Sopenharmony_ci debugfs_remove_recursive(hpre_debugfs_root); 151862306a36Sopenharmony_ci} 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_cistatic int __init hpre_init(void) 152162306a36Sopenharmony_ci{ 152262306a36Sopenharmony_ci int ret; 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci hisi_qm_init_list(&hpre_devices); 152562306a36Sopenharmony_ci hpre_register_debugfs(); 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci ret = pci_register_driver(&hpre_pci_driver); 152862306a36Sopenharmony_ci if (ret) { 152962306a36Sopenharmony_ci hpre_unregister_debugfs(); 153062306a36Sopenharmony_ci pr_err("hpre: can't register hisi hpre driver.\n"); 153162306a36Sopenharmony_ci } 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci return ret; 153462306a36Sopenharmony_ci} 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_cistatic void __exit hpre_exit(void) 153762306a36Sopenharmony_ci{ 153862306a36Sopenharmony_ci pci_unregister_driver(&hpre_pci_driver); 153962306a36Sopenharmony_ci hpre_unregister_debugfs(); 154062306a36Sopenharmony_ci} 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_cimodule_init(hpre_init); 154362306a36Sopenharmony_cimodule_exit(hpre_exit); 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 154662306a36Sopenharmony_ciMODULE_AUTHOR("Zaibo Xu <xuzaibo@huawei.com>"); 154762306a36Sopenharmony_ciMODULE_AUTHOR("Meng Yu <yumeng18@huawei.com>"); 154862306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver for HiSilicon HPRE accelerator"); 1549