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