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