xref: /optee_os/core/drivers/crypto/hisilicon/hpre_main.c (revision b6a44cc5a792f1ca0c8f4fc0a9ae33f1017c1e2f)
19e255282Sloubaihui // SPDX-License-Identifier: BSD-2-Clause
29e255282Sloubaihui /*
39e255282Sloubaihui  * Copyright 2024 HiSilicon Limited.
49e255282Sloubaihui  * Kunpeng hardware accelerator HPRE module init.
59e255282Sloubaihui  */
679502744Syuzexi 
779502744Syuzexi #include <initcall.h>
89e255282Sloubaihui 
9*b6a44cc5Sleisen #include "hpre_main.h"
10*b6a44cc5Sleisen 
119e255282Sloubaihui /* base config */
129e255282Sloubaihui #define HPRE_COMMON_CNT_CLR_CE		0x301000
139e255282Sloubaihui #define HPRE_CFG_AXCACHE		0x301010
149e255282Sloubaihui #define HPRE_RDCHN_INI_CFG		0x301014
159e255282Sloubaihui #define HPRE_BD_ENDIAN			0x301020
169e255282Sloubaihui #define HPRE_ECC_BYPASS			0x301024
179e255282Sloubaihui #define HPRE_POISON_BYPASS		0x30102c
189e255282Sloubaihui #define HPRE_BD_ARUSR_CFG		0x301030
199e255282Sloubaihui #define HPRE_BD_AWUSR_CFG		0x301034
209e255282Sloubaihui #define HPRE_TYPES_ENB			0x301038
219e255282Sloubaihui #define HPRE_DATA_RUSER_CFG		0x30103c
229e255282Sloubaihui #define HPRE_DATA_WUSER_CFG		0x301040
239e255282Sloubaihui #define HPRE_HAC_INT_MASK		0x301400
249e255282Sloubaihui #define HPRE_RAS_ECC_1BIT_TH		0x30140c
259e255282Sloubaihui #define HPRE_RAS_CE_ENB			0x301410
269e255282Sloubaihui #define HPRE_RAS_NFE_ENB		0x301414
279e255282Sloubaihui #define HPRE_RAS_FE_ENB			0x301418
289e255282Sloubaihui #define HPRE_HAC_INT_SRC		0x301600
299e255282Sloubaihui #define HPRE_RDCHN_INI_ST		0x301a00
309e255282Sloubaihui #define HPRE_OOO_SHUTDOWN_SEL		0x301a3c
319e255282Sloubaihui #define HPRE_CORE_ENB			0x302004
329e255282Sloubaihui #define HPRE_CORE_INI_CFG		0x302020
339e255282Sloubaihui #define HPRE_CORE_INI_STATUS		0x302080
349e255282Sloubaihui /* clock gate */
359e255282Sloubaihui #define HPRE_CLKGATE_CTL		0x301a10
369e255282Sloubaihui #define HPRE_PEH_CFG_AUTO_GATE		0x301a2c
379e255282Sloubaihui #define HPRE_CLUSTER_DYN_CTL		0x302010
389e255282Sloubaihui #define HPRE_CORE_SHB_CFG		0x302088
399e255282Sloubaihui #define HPRE_CORE_GATE_ENABLE		GENMASK_32(31, 30)
409e255282Sloubaihui 
419e255282Sloubaihui #define HPRE_AXCACHE_MASK		0xff
429e255282Sloubaihui #define HPRE_HAC_INT_DISABLE		0x1ffffff
439e255282Sloubaihui #define HPRE_RAS_CE_MASK		0x1
449e255282Sloubaihui #define HPRE_RAS_NFE_MASK		0x1fffffe
459e255282Sloubaihui #define HPRE_RAS_FE_MASK		0
469e255282Sloubaihui #define HPRE_BD_LITTLE_ENDIAN		0
479e255282Sloubaihui #define HPRE_RSA_ENB			BIT(0)
489e255282Sloubaihui #define HPRE_ECC_ENB			BIT(1)
499e255282Sloubaihui #define HPRE_BD_ARUSR_MASK		0x2
509e255282Sloubaihui #define HPRE_BD_AWUSR_MASK		0x102
519e255282Sloubaihui #define HPRE_DATA_USR_MASK		0x32
529e255282Sloubaihui #define HPRE_CLUSTER_CORE_MASK		GENMASK_32(9, 0)
539e255282Sloubaihui 
549e255282Sloubaihui static SLIST_HEAD(, acc_device) hpre_list = SLIST_HEAD_INITIALIZER(hpre_list);
559e255282Sloubaihui 
hpre_create_qp(uint8_t sq_type)569e255282Sloubaihui struct hisi_qp *hpre_create_qp(uint8_t sq_type)
579e255282Sloubaihui {
589e255282Sloubaihui 	struct acc_device *hpre_dev = NULL;
599e255282Sloubaihui 	struct acc_device *cur_dev = NULL;
609e255282Sloubaihui 	struct hisi_qm *qm = NULL;
619e255282Sloubaihui 	uint32_t free_qp_num = 0;
629e255282Sloubaihui 	uint32_t max_qp_num = 0;
639e255282Sloubaihui 
649e255282Sloubaihui 	/* Find the HPRE device with the most remaining qp numbers */
659e255282Sloubaihui 	SLIST_FOREACH(cur_dev, &hpre_list, link) {
669e255282Sloubaihui 		qm = &cur_dev->qm;
679e255282Sloubaihui 		if (qm->fun_type == HISI_QM_HW_PF)
689e255282Sloubaihui 			free_qp_num = HISI_QM_PF_Q_NUM - qm->qp_in_used;
699e255282Sloubaihui 		else
709e255282Sloubaihui 			free_qp_num = HISI_QM_VF_Q_NUM - qm->qp_in_used;
719e255282Sloubaihui 		if (free_qp_num > max_qp_num) {
729e255282Sloubaihui 			max_qp_num = free_qp_num;
739e255282Sloubaihui 			hpre_dev = cur_dev;
749e255282Sloubaihui 		}
759e255282Sloubaihui 	}
769e255282Sloubaihui 
779e255282Sloubaihui 	if (!hpre_dev) {
789e255282Sloubaihui 		EMSG("No available hpre device");
799e255282Sloubaihui 		return NULL;
809e255282Sloubaihui 	}
819e255282Sloubaihui 
829e255282Sloubaihui 	return hisi_qm_create_qp(&hpre_dev->qm, sq_type);
839e255282Sloubaihui }
849e255282Sloubaihui 
hpre_bin_from_crypto_bin(uint8_t * dst,const uint8_t * src,uint32_t bsize,uint32_t dsize)859e255282Sloubaihui enum hisi_drv_status hpre_bin_from_crypto_bin(uint8_t *dst, const uint8_t *src,
869e255282Sloubaihui 					      uint32_t bsize, uint32_t dsize)
879e255282Sloubaihui {
889e255282Sloubaihui 	if (!src || !dst || !dsize || !bsize) {
899e255282Sloubaihui 		EMSG("parameter error");
909e255282Sloubaihui 		return HISI_QM_DRVCRYPT_EINVAL;
919e255282Sloubaihui 	}
929e255282Sloubaihui 
939e255282Sloubaihui 	if (bsize < dsize) {
949e255282Sloubaihui 		EMSG("dsize is too long");
959e255282Sloubaihui 		return HISI_QM_DRVCRYPT_EINVAL;
969e255282Sloubaihui 	}
979e255282Sloubaihui 
989e255282Sloubaihui 	if (src == dst && bsize == dsize)
999e255282Sloubaihui 		return HISI_QM_DRVCRYPT_NO_ERR;
1009e255282Sloubaihui 
1019e255282Sloubaihui 	/*
1029e255282Sloubaihui 	 * Copying non-zero data and padding with zeroes in high-bits
1039e255282Sloubaihui 	 * (eg: 1 2 3 0 0 -> 0 0 1 2 3)
1049e255282Sloubaihui 	 */
1059e255282Sloubaihui 	memmove(dst + bsize - dsize, src, dsize);
1069e255282Sloubaihui 	memset(dst, 0, bsize - dsize);
1079e255282Sloubaihui 
1089e255282Sloubaihui 	return HISI_QM_DRVCRYPT_NO_ERR;
1099e255282Sloubaihui }
1109e255282Sloubaihui 
hpre_bin_to_crypto_bin(uint8_t * dst,const uint8_t * src,uint32_t bsize,uint32_t dsize)1119e255282Sloubaihui enum hisi_drv_status hpre_bin_to_crypto_bin(uint8_t *dst, const uint8_t *src,
1129e255282Sloubaihui 					    uint32_t bsize, uint32_t dsize)
1139e255282Sloubaihui {
1149e255282Sloubaihui 	if (!dst || !src || !bsize || !dsize) {
1159e255282Sloubaihui 		EMSG("parameter error");
1169e255282Sloubaihui 		return HISI_QM_DRVCRYPT_EINVAL;
1179e255282Sloubaihui 	}
1189e255282Sloubaihui 
1199e255282Sloubaihui 	if (bsize < dsize) {
1209e255282Sloubaihui 		EMSG("dsize is too long");
1219e255282Sloubaihui 		return HISI_QM_DRVCRYPT_EINVAL;
1229e255282Sloubaihui 	}
1239e255282Sloubaihui 
1249e255282Sloubaihui 	if (src == dst && bsize == dsize)
1259e255282Sloubaihui 		return HISI_QM_DRVCRYPT_NO_ERR;
1269e255282Sloubaihui 	/*
1279e255282Sloubaihui 	 * Copying non-zero data and padding with zeroes in low-bits
1289e255282Sloubaihui 	 * (eg: 0 0 1 2 3 -> 1 2 3 0 0)
1299e255282Sloubaihui 	 */
1309e255282Sloubaihui 	memmove(dst, src + bsize - dsize, dsize);
1319e255282Sloubaihui 	memset(dst + dsize, 0, bsize - dsize);
1329e255282Sloubaihui 
1339e255282Sloubaihui 	return HISI_QM_DRVCRYPT_NO_ERR;
1349e255282Sloubaihui }
1359e255282Sloubaihui 
hpre_set_cluster(struct hisi_qm * qm)1369e255282Sloubaihui static enum hisi_drv_status hpre_set_cluster(struct hisi_qm *qm)
1379e255282Sloubaihui {
1389e255282Sloubaihui 	uint32_t val = 0;
1399e255282Sloubaihui 
1409e255282Sloubaihui 	io_write32(qm->io_base + HPRE_CORE_ENB, HPRE_CLUSTER_CORE_MASK);
1419e255282Sloubaihui 	io_write32(qm->io_base + HPRE_CORE_INI_CFG, 0x1);
1429e255282Sloubaihui 
1439e255282Sloubaihui 	if (IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_CORE_INI_STATUS, val,
1449e255282Sloubaihui 				   (val & HPRE_CLUSTER_CORE_MASK) ==
1459e255282Sloubaihui 				   HPRE_CLUSTER_CORE_MASK, POLL_PERIOD,
1469e255282Sloubaihui 				   POLL_TIMEOUT))
1479e255282Sloubaihui 		return HISI_QM_DRVCRYPT_EBUSY;
1489e255282Sloubaihui 	return HISI_QM_DRVCRYPT_NO_ERR;
1499e255282Sloubaihui }
1509e255282Sloubaihui 
hpre_disable_clock_gate(struct hisi_qm * qm)1519e255282Sloubaihui static void hpre_disable_clock_gate(struct hisi_qm *qm)
1529e255282Sloubaihui {
1539e255282Sloubaihui 	io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x0);
1549e255282Sloubaihui 	io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x0);
1559e255282Sloubaihui 	io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x0);
1569e255282Sloubaihui 	io_clrbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE);
1579e255282Sloubaihui }
1589e255282Sloubaihui 
hpre_enable_clock_gate(struct hisi_qm * qm)1599e255282Sloubaihui static void hpre_enable_clock_gate(struct hisi_qm *qm)
1609e255282Sloubaihui {
1619e255282Sloubaihui 	io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x1);
1629e255282Sloubaihui 	io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x1);
1639e255282Sloubaihui 	io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x1);
1649e255282Sloubaihui 	io_setbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE);
1659e255282Sloubaihui }
1669e255282Sloubaihui 
hpre_engine_init(struct acc_device * hpre_dev)1679e255282Sloubaihui static TEE_Result hpre_engine_init(struct acc_device *hpre_dev)
1689e255282Sloubaihui {
1699e255282Sloubaihui 	struct hisi_qm *qm = &hpre_dev->qm;
1709e255282Sloubaihui 	uint32_t val = 0;
1719e255282Sloubaihui 	int32_t ret = 0;
1729e255282Sloubaihui 
1739e255282Sloubaihui 	if (qm->fun_type == HISI_QM_HW_VF)
1749e255282Sloubaihui 		return TEE_SUCCESS;
1759e255282Sloubaihui 
1769e255282Sloubaihui 	hpre_disable_clock_gate(qm);
1779e255282Sloubaihui 	hisi_qm_dev_init(qm);
1789e255282Sloubaihui 
1799e255282Sloubaihui 	io_write32(qm->io_base + HPRE_CFG_AXCACHE, HPRE_AXCACHE_MASK);
1809e255282Sloubaihui 	io_write32(qm->io_base + HPRE_BD_ENDIAN, HPRE_BD_LITTLE_ENDIAN);
1819e255282Sloubaihui 	io_write32(qm->io_base + HPRE_RAS_CE_ENB, HPRE_RAS_CE_MASK);
1829e255282Sloubaihui 	io_write32(qm->io_base + HPRE_RAS_NFE_ENB, HPRE_RAS_NFE_MASK);
1839e255282Sloubaihui 	io_write32(qm->io_base + HPRE_RAS_FE_ENB, HPRE_RAS_FE_MASK);
1849e255282Sloubaihui 	io_write32(qm->io_base + HPRE_HAC_INT_MASK, HPRE_HAC_INT_DISABLE);
1859e255282Sloubaihui 	io_write32(qm->io_base + HPRE_POISON_BYPASS, 0x0);
1869e255282Sloubaihui 	io_write32(qm->io_base + HPRE_COMMON_CNT_CLR_CE, 0x0);
1879e255282Sloubaihui 	io_write32(qm->io_base + HPRE_ECC_BYPASS, 0x0);
1889e255282Sloubaihui 	/* cmd_type is controlled by hac subctrl */
1899e255282Sloubaihui 	io_write32(qm->io_base + HPRE_BD_ARUSR_CFG, HPRE_BD_ARUSR_MASK);
1909e255282Sloubaihui 	io_write32(qm->io_base + HPRE_BD_AWUSR_CFG, HPRE_BD_AWUSR_MASK);
1919e255282Sloubaihui 	io_write32(qm->io_base + HPRE_DATA_RUSER_CFG, HPRE_DATA_USR_MASK);
1929e255282Sloubaihui 	io_write32(qm->io_base + HPRE_DATA_WUSER_CFG, HPRE_DATA_USR_MASK);
1939e255282Sloubaihui 	io_write32(qm->io_base + HPRE_TYPES_ENB, HPRE_RSA_ENB | HPRE_ECC_ENB);
1949e255282Sloubaihui 	io_write32(qm->io_base + HPRE_RDCHN_INI_CFG, 0x1);
1959e255282Sloubaihui 	ret = IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_RDCHN_INI_ST, val,
1969e255282Sloubaihui 				     val & 0x1, POLL_PERIOD, POLL_TIMEOUT);
1979e255282Sloubaihui 	if (ret) {
1989e255282Sloubaihui 		EMSG("Fail to init rd channel");
1999e255282Sloubaihui 		return TEE_ERROR_BUSY;
2009e255282Sloubaihui 	}
2019e255282Sloubaihui 
2029e255282Sloubaihui 	ret = hpre_set_cluster(qm);
2039e255282Sloubaihui 	if (ret) {
2049e255282Sloubaihui 		EMSG("Fail to init hpre cluster cores");
2059e255282Sloubaihui 		return TEE_ERROR_BUSY;
2069e255282Sloubaihui 	}
2079e255282Sloubaihui 
2089e255282Sloubaihui 	hpre_enable_clock_gate(qm);
2099e255282Sloubaihui 
2109e255282Sloubaihui 	return TEE_SUCCESS;
2119e255282Sloubaihui }
2129e255282Sloubaihui 
hpre_dev_status_check(struct hisi_qm * qm)2139e255282Sloubaihui static enum hisi_drv_status hpre_dev_status_check(struct hisi_qm *qm)
2149e255282Sloubaihui {
2159e255282Sloubaihui 	uint32_t val = 0;
2169e255282Sloubaihui 
2179e255282Sloubaihui 	val = io_read32(qm->io_base + HPRE_HAC_INT_SRC);
2189e255282Sloubaihui 	if (val & HPRE_RAS_NFE_MASK) {
2199e255282Sloubaihui 		EMSG("HPRE NFE RAS happened, need to reset");
2209e255282Sloubaihui 		return HISI_QM_DRVCRYPT_HW_EACCESS;
2219e255282Sloubaihui 	}
2229e255282Sloubaihui 
2239e255282Sloubaihui 	val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC);
2249e255282Sloubaihui 	if (val) {
2259e255282Sloubaihui 		if (val & HISI_QM_HPRE_NFE_INT_MASK)
2269e255282Sloubaihui 			EMSG("QM NFE RAS happened, need to reset");
2279e255282Sloubaihui 
2289e255282Sloubaihui 		if (val & HISI_QM_INVALID_DB) {
2299e255282Sloubaihui 			EMSG("QM invalid db happened, please check");
2309e255282Sloubaihui 			io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC,
2319e255282Sloubaihui 				   HISI_QM_INVALID_DB);
2329e255282Sloubaihui 		}
2339e255282Sloubaihui 
2349e255282Sloubaihui 		return HISI_QM_DRVCRYPT_HW_EACCESS;
2359e255282Sloubaihui 	}
2369e255282Sloubaihui 
2379e255282Sloubaihui 	return HISI_QM_DRVCRYPT_NO_ERR;
2389e255282Sloubaihui }
2399e255282Sloubaihui 
hpre_qm_init(struct acc_device * hpre_dev)2409e255282Sloubaihui static enum hisi_drv_status hpre_qm_init(struct acc_device *hpre_dev)
2419e255282Sloubaihui {
2429e255282Sloubaihui 	struct hisi_qm *qm = &hpre_dev->qm;
2439e255282Sloubaihui 
2449e255282Sloubaihui 	if (cpu_mmu_enabled()) {
2459e255282Sloubaihui 		qm->io_base = (uintptr_t)phys_to_virt_io(hpre_dev->io_base,
2469e255282Sloubaihui 							 hpre_dev->io_size);
2479e255282Sloubaihui 		if (!qm->io_base) {
2489e255282Sloubaihui 			EMSG("Fail to get qm io_base");
2499e255282Sloubaihui 			return HISI_QM_DRVCRYPT_EFAULT;
2509e255282Sloubaihui 		}
2519e255282Sloubaihui 	} else {
2529e255282Sloubaihui 		qm->io_base = hpre_dev->io_base;
2539e255282Sloubaihui 	}
2549e255282Sloubaihui 
2559e255282Sloubaihui 	qm->vfs_num = hpre_dev->vfs_num;
2569e255282Sloubaihui 	qm->fun_type = hpre_dev->fun_type;
2579e255282Sloubaihui 	qm->sqe_size = HPRE_SQE_SIZE;
2589e255282Sloubaihui 	qm->sqe_log2_size = HPRE_SQE_LOG2_SIZE;
2599e255282Sloubaihui 	if (qm->fun_type == HISI_QM_HW_PF) {
2609e255282Sloubaihui 		hisi_qm_get_version(qm);
2619e255282Sloubaihui 		DMSG("HPRE hardware version is 0x%"PRIx32, qm->version);
2629e255282Sloubaihui 		qm->qp_base = HISI_QM_PF_Q_BASE;
2639e255282Sloubaihui 		qm->qp_num = HISI_QM_PF_Q_NUM;
2649e255282Sloubaihui 		qm->dev_status_check = hpre_dev_status_check;
2659e255282Sloubaihui 	}
2669e255282Sloubaihui 
2679e255282Sloubaihui 	return hisi_qm_init(qm);
2689e255282Sloubaihui }
2699e255282Sloubaihui 
hpre_pre_init(void)2709e255282Sloubaihui static struct acc_device *hpre_pre_init(void)
2719e255282Sloubaihui {
2729e255282Sloubaihui 	struct acc_device *hpre_dev = NULL;
2739e255282Sloubaihui 
2749e255282Sloubaihui 	hpre_dev = calloc(1, sizeof(*hpre_dev));
2759e255282Sloubaihui 	if (!hpre_dev) {
2769e255282Sloubaihui 		EMSG("Fail to alloc hpre_dev");
2779e255282Sloubaihui 		return NULL;
2789e255282Sloubaihui 	}
2799e255282Sloubaihui 
2809e255282Sloubaihui 	hpre_dev->io_base = HPRE_BAR_BASE;
2819e255282Sloubaihui 	hpre_dev->io_size = HPRE_BAR_SIZE;
2829e255282Sloubaihui 	hpre_dev->fun_type = HISI_QM_HW_PF;
2839e255282Sloubaihui 	SLIST_INSERT_HEAD(&hpre_list, hpre_dev, link);
2849e255282Sloubaihui 
2859e255282Sloubaihui 	return hpre_dev;
2869e255282Sloubaihui }
2879e255282Sloubaihui 
hpre_probe(void)2889e255282Sloubaihui static TEE_Result hpre_probe(void)
2899e255282Sloubaihui {
2909e255282Sloubaihui 	TEE_Result ret = TEE_ERROR_GENERIC;
2919e255282Sloubaihui 	struct acc_device *hpre_dev = NULL;
2929e255282Sloubaihui 	struct hisi_qm *qm = NULL;
2939e255282Sloubaihui 
2949e255282Sloubaihui 	DMSG("HPRE driver init start");
2959e255282Sloubaihui 	hpre_dev = hpre_pre_init();
2969e255282Sloubaihui 	if (!hpre_dev)
2979e255282Sloubaihui 		return TEE_ERROR_OUT_OF_MEMORY;
2989e255282Sloubaihui 
2999e255282Sloubaihui 	qm = &hpre_dev->qm;
3009e255282Sloubaihui 	if (hpre_qm_init(hpre_dev)) {
3019e255282Sloubaihui 		EMSG("Fail to init hpre qm");
3029e255282Sloubaihui 		goto err_with_pre_init;
3039e255282Sloubaihui 	}
3049e255282Sloubaihui 
3059e255282Sloubaihui 	ret = hpre_engine_init(hpre_dev);
3069e255282Sloubaihui 	if (ret) {
3079e255282Sloubaihui 		EMSG("Fail to init engine");
3089e255282Sloubaihui 		goto err_with_qm_init;
3099e255282Sloubaihui 	}
3109e255282Sloubaihui 
3119e255282Sloubaihui 	if (hisi_qm_start(qm)) {
3129e255282Sloubaihui 		EMSG("Fail to start qm");
3139e255282Sloubaihui 		ret = TEE_ERROR_BAD_STATE;
3149e255282Sloubaihui 		goto err_with_qm_init;
3159e255282Sloubaihui 	}
3169e255282Sloubaihui 
3179e255282Sloubaihui 	DMSG("HPRE driver init done");
3189e255282Sloubaihui 	return TEE_SUCCESS;
3199e255282Sloubaihui 
3209e255282Sloubaihui err_with_qm_init:
3219e255282Sloubaihui 	hisi_qm_uninit(qm);
3229e255282Sloubaihui err_with_pre_init:
3239e255282Sloubaihui 	SLIST_REMOVE_HEAD(&hpre_list, link);
3249e255282Sloubaihui 	free(hpre_dev);
3259e255282Sloubaihui 
3269e255282Sloubaihui 	return ret;
3279e255282Sloubaihui }
3289e255282Sloubaihui 
3299e255282Sloubaihui driver_init(hpre_probe);
330