18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for the Hisilicon SEC units found on Hip06 Hip07 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017 Hisilicon Limited. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/acpi.h> 88c2ecf20Sopenharmony_ci#include <linux/atomic.h> 98c2ecf20Sopenharmony_ci#include <linux/delay.h> 108c2ecf20Sopenharmony_ci#include <linux/dma-direction.h> 118c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 128c2ecf20Sopenharmony_ci#include <linux/dmapool.h> 138c2ecf20Sopenharmony_ci#include <linux/io.h> 148c2ecf20Sopenharmony_ci#include <linux/iommu.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/irq.h> 178c2ecf20Sopenharmony_ci#include <linux/irqreturn.h> 188c2ecf20Sopenharmony_ci#include <linux/mm.h> 198c2ecf20Sopenharmony_ci#include <linux/module.h> 208c2ecf20Sopenharmony_ci#include <linux/of.h> 218c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "sec_drv.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define SEC_QUEUE_AR_FROCE_ALLOC 0 278c2ecf20Sopenharmony_ci#define SEC_QUEUE_AR_FROCE_NOALLOC 1 288c2ecf20Sopenharmony_ci#define SEC_QUEUE_AR_FROCE_DIS 2 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define SEC_QUEUE_AW_FROCE_ALLOC 0 318c2ecf20Sopenharmony_ci#define SEC_QUEUE_AW_FROCE_NOALLOC 1 328c2ecf20Sopenharmony_ci#define SEC_QUEUE_AW_FROCE_DIS 2 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* SEC_ALGSUB registers */ 358c2ecf20Sopenharmony_ci#define SEC_ALGSUB_CLK_EN_REG 0x03b8 368c2ecf20Sopenharmony_ci#define SEC_ALGSUB_CLK_DIS_REG 0x03bc 378c2ecf20Sopenharmony_ci#define SEC_ALGSUB_CLK_ST_REG 0x535c 388c2ecf20Sopenharmony_ci#define SEC_ALGSUB_RST_REQ_REG 0x0aa8 398c2ecf20Sopenharmony_ci#define SEC_ALGSUB_RST_DREQ_REG 0x0aac 408c2ecf20Sopenharmony_ci#define SEC_ALGSUB_RST_ST_REG 0x5a54 418c2ecf20Sopenharmony_ci#define SEC_ALGSUB_RST_ST_IS_RST BIT(0) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define SEC_ALGSUB_BUILD_RST_REQ_REG 0x0ab8 448c2ecf20Sopenharmony_ci#define SEC_ALGSUB_BUILD_RST_DREQ_REG 0x0abc 458c2ecf20Sopenharmony_ci#define SEC_ALGSUB_BUILD_RST_ST_REG 0x5a5c 468c2ecf20Sopenharmony_ci#define SEC_ALGSUB_BUILD_RST_ST_IS_RST BIT(0) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define SEC_SAA_BASE 0x00001000UL 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* SEC_SAA registers */ 518c2ecf20Sopenharmony_ci#define SEC_SAA_CTRL_REG(x) ((x) * SEC_SAA_ADDR_SIZE) 528c2ecf20Sopenharmony_ci#define SEC_SAA_CTRL_GET_QM_EN BIT(0) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define SEC_ST_INTMSK1_REG 0x0200 558c2ecf20Sopenharmony_ci#define SEC_ST_RINT1_REG 0x0400 568c2ecf20Sopenharmony_ci#define SEC_ST_INTSTS1_REG 0x0600 578c2ecf20Sopenharmony_ci#define SEC_BD_MNG_STAT_REG 0x0800 588c2ecf20Sopenharmony_ci#define SEC_PARSING_STAT_REG 0x0804 598c2ecf20Sopenharmony_ci#define SEC_LOAD_TIME_OUT_CNT_REG 0x0808 608c2ecf20Sopenharmony_ci#define SEC_CORE_WORK_TIME_OUT_CNT_REG 0x080c 618c2ecf20Sopenharmony_ci#define SEC_BACK_TIME_OUT_CNT_REG 0x0810 628c2ecf20Sopenharmony_ci#define SEC_BD1_PARSING_RD_TIME_OUT_CNT_REG 0x0814 638c2ecf20Sopenharmony_ci#define SEC_BD1_PARSING_WR_TIME_OUT_CNT_REG 0x0818 648c2ecf20Sopenharmony_ci#define SEC_BD2_PARSING_RD_TIME_OUT_CNT_REG 0x081c 658c2ecf20Sopenharmony_ci#define SEC_BD2_PARSING_WR_TIME_OUT_CNT_REG 0x0820 668c2ecf20Sopenharmony_ci#define SEC_SAA_ACC_REG 0x083c 678c2ecf20Sopenharmony_ci#define SEC_BD_NUM_CNT_IN_SEC_REG 0x0858 688c2ecf20Sopenharmony_ci#define SEC_LOAD_WORK_TIME_CNT_REG 0x0860 698c2ecf20Sopenharmony_ci#define SEC_CORE_WORK_WORK_TIME_CNT_REG 0x0864 708c2ecf20Sopenharmony_ci#define SEC_BACK_WORK_TIME_CNT_REG 0x0868 718c2ecf20Sopenharmony_ci#define SEC_SAA_IDLE_TIME_CNT_REG 0x086c 728c2ecf20Sopenharmony_ci#define SEC_SAA_CLK_CNT_REG 0x0870 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* SEC_COMMON registers */ 758c2ecf20Sopenharmony_ci#define SEC_CLK_EN_REG 0x0000 768c2ecf20Sopenharmony_ci#define SEC_CTRL_REG 0x0004 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define SEC_COMMON_CNT_CLR_CE_REG 0x0008 798c2ecf20Sopenharmony_ci#define SEC_COMMON_CNT_CLR_CE_CLEAR BIT(0) 808c2ecf20Sopenharmony_ci#define SEC_COMMON_CNT_CLR_CE_SNAP_EN BIT(1) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#define SEC_SECURE_CTRL_REG 0x000c 838c2ecf20Sopenharmony_ci#define SEC_AXI_CACHE_CFG_REG 0x0010 848c2ecf20Sopenharmony_ci#define SEC_AXI_QOS_CFG_REG 0x0014 858c2ecf20Sopenharmony_ci#define SEC_IPV4_MASK_TABLE_REG 0x0020 868c2ecf20Sopenharmony_ci#define SEC_IPV6_MASK_TABLE_X_REG(x) (0x0024 + (x) * 4) 878c2ecf20Sopenharmony_ci#define SEC_FSM_MAX_CNT_REG 0x0064 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define SEC_CTRL2_REG 0x0068 908c2ecf20Sopenharmony_ci#define SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_M GENMASK(3, 0) 918c2ecf20Sopenharmony_ci#define SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_S 0 928c2ecf20Sopenharmony_ci#define SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_M GENMASK(6, 4) 938c2ecf20Sopenharmony_ci#define SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_S 4 948c2ecf20Sopenharmony_ci#define SEC_CTRL2_CLK_GATE_EN BIT(7) 958c2ecf20Sopenharmony_ci#define SEC_CTRL2_ENDIAN_BD BIT(8) 968c2ecf20Sopenharmony_ci#define SEC_CTRL2_ENDIAN_BD_TYPE BIT(9) 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define SEC_CNT_PRECISION_CFG_REG 0x006c 998c2ecf20Sopenharmony_ci#define SEC_DEBUG_BD_CFG_REG 0x0070 1008c2ecf20Sopenharmony_ci#define SEC_DEBUG_BD_CFG_WB_NORMAL BIT(0) 1018c2ecf20Sopenharmony_ci#define SEC_DEBUG_BD_CFG_WB_EN BIT(1) 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define SEC_Q_SIGHT_SEL 0x0074 1048c2ecf20Sopenharmony_ci#define SEC_Q_SIGHT_HIS_CLR 0x0078 1058c2ecf20Sopenharmony_ci#define SEC_Q_VMID_CFG_REG(q) (0x0100 + (q) * 4) 1068c2ecf20Sopenharmony_ci#define SEC_Q_WEIGHT_CFG_REG(q) (0x200 + (q) * 4) 1078c2ecf20Sopenharmony_ci#define SEC_STAT_CLR_REG 0x0a00 1088c2ecf20Sopenharmony_ci#define SEC_SAA_IDLE_CNT_CLR_REG 0x0a04 1098c2ecf20Sopenharmony_ci#define SEC_QM_CPL_Q_IDBUF_DFX_CFG_REG 0x0b00 1108c2ecf20Sopenharmony_ci#define SEC_QM_CPL_Q_IDBUF_DFX_RESULT_REG 0x0b04 1118c2ecf20Sopenharmony_ci#define SEC_QM_BD_DFX_CFG_REG 0x0b08 1128c2ecf20Sopenharmony_ci#define SEC_QM_BD_DFX_RESULT_REG 0x0b0c 1138c2ecf20Sopenharmony_ci#define SEC_QM_BDID_DFX_RESULT_REG 0x0b10 1148c2ecf20Sopenharmony_ci#define SEC_QM_BD_DFIFO_STATUS_REG 0x0b14 1158c2ecf20Sopenharmony_ci#define SEC_QM_BD_DFX_CFG2_REG 0x0b1c 1168c2ecf20Sopenharmony_ci#define SEC_QM_BD_DFX_RESULT2_REG 0x0b20 1178c2ecf20Sopenharmony_ci#define SEC_QM_BD_IDFIFO_STATUS_REG 0x0b18 1188c2ecf20Sopenharmony_ci#define SEC_QM_BD_DFIFO_STATUS2_REG 0x0b28 1198c2ecf20Sopenharmony_ci#define SEC_QM_BD_IDFIFO_STATUS2_REG 0x0b2c 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci#define SEC_HASH_IPV4_MASK 0xfff00000 1228c2ecf20Sopenharmony_ci#define SEC_MAX_SAA_NUM 0xa 1238c2ecf20Sopenharmony_ci#define SEC_SAA_ADDR_SIZE 0x1000 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#define SEC_Q_INIT_REG 0x0 1268c2ecf20Sopenharmony_ci#define SEC_Q_INIT_WO_STAT_CLEAR 0x2 1278c2ecf20Sopenharmony_ci#define SEC_Q_INIT_AND_STAT_CLEAR 0x3 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#define SEC_Q_CFG_REG 0x8 1308c2ecf20Sopenharmony_ci#define SEC_Q_CFG_REORDER BIT(0) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#define SEC_Q_PROC_NUM_CFG_REG 0x10 1338c2ecf20Sopenharmony_ci#define SEC_QUEUE_ENB_REG 0x18 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci#define SEC_Q_DEPTH_CFG_REG 0x50 1368c2ecf20Sopenharmony_ci#define SEC_Q_DEPTH_CFG_DEPTH_M GENMASK(11, 0) 1378c2ecf20Sopenharmony_ci#define SEC_Q_DEPTH_CFG_DEPTH_S 0 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci#define SEC_Q_BASE_HADDR_REG 0x54 1408c2ecf20Sopenharmony_ci#define SEC_Q_BASE_LADDR_REG 0x58 1418c2ecf20Sopenharmony_ci#define SEC_Q_WR_PTR_REG 0x5c 1428c2ecf20Sopenharmony_ci#define SEC_Q_OUTORDER_BASE_HADDR_REG 0x60 1438c2ecf20Sopenharmony_ci#define SEC_Q_OUTORDER_BASE_LADDR_REG 0x64 1448c2ecf20Sopenharmony_ci#define SEC_Q_OUTORDER_RD_PTR_REG 0x68 1458c2ecf20Sopenharmony_ci#define SEC_Q_OT_TH_REG 0x6c 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#define SEC_Q_ARUSER_CFG_REG 0x70 1488c2ecf20Sopenharmony_ci#define SEC_Q_ARUSER_CFG_FA BIT(0) 1498c2ecf20Sopenharmony_ci#define SEC_Q_ARUSER_CFG_FNA BIT(1) 1508c2ecf20Sopenharmony_ci#define SEC_Q_ARUSER_CFG_RINVLD BIT(2) 1518c2ecf20Sopenharmony_ci#define SEC_Q_ARUSER_CFG_PKG BIT(3) 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#define SEC_Q_AWUSER_CFG_REG 0x74 1548c2ecf20Sopenharmony_ci#define SEC_Q_AWUSER_CFG_FA BIT(0) 1558c2ecf20Sopenharmony_ci#define SEC_Q_AWUSER_CFG_FNA BIT(1) 1568c2ecf20Sopenharmony_ci#define SEC_Q_AWUSER_CFG_PKG BIT(2) 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci#define SEC_Q_ERR_BASE_HADDR_REG 0x7c 1598c2ecf20Sopenharmony_ci#define SEC_Q_ERR_BASE_LADDR_REG 0x80 1608c2ecf20Sopenharmony_ci#define SEC_Q_CFG_VF_NUM_REG 0x84 1618c2ecf20Sopenharmony_ci#define SEC_Q_SOFT_PROC_PTR_REG 0x88 1628c2ecf20Sopenharmony_ci#define SEC_Q_FAIL_INT_MSK_REG 0x300 1638c2ecf20Sopenharmony_ci#define SEC_Q_FLOW_INT_MKS_REG 0x304 1648c2ecf20Sopenharmony_ci#define SEC_Q_FAIL_RINT_REG 0x400 1658c2ecf20Sopenharmony_ci#define SEC_Q_FLOW_RINT_REG 0x404 1668c2ecf20Sopenharmony_ci#define SEC_Q_FAIL_INT_STATUS_REG 0x500 1678c2ecf20Sopenharmony_ci#define SEC_Q_FLOW_INT_STATUS_REG 0x504 1688c2ecf20Sopenharmony_ci#define SEC_Q_STATUS_REG 0x600 1698c2ecf20Sopenharmony_ci#define SEC_Q_RD_PTR_REG 0x604 1708c2ecf20Sopenharmony_ci#define SEC_Q_PRO_PTR_REG 0x608 1718c2ecf20Sopenharmony_ci#define SEC_Q_OUTORDER_WR_PTR_REG 0x60c 1728c2ecf20Sopenharmony_ci#define SEC_Q_OT_CNT_STATUS_REG 0x610 1738c2ecf20Sopenharmony_ci#define SEC_Q_INORDER_BD_NUM_ST_REG 0x650 1748c2ecf20Sopenharmony_ci#define SEC_Q_INORDER_GET_FLAG_ST_REG 0x654 1758c2ecf20Sopenharmony_ci#define SEC_Q_INORDER_ADD_FLAG_ST_REG 0x658 1768c2ecf20Sopenharmony_ci#define SEC_Q_INORDER_TASK_INT_NUM_LEFT_ST_REG 0x65c 1778c2ecf20Sopenharmony_ci#define SEC_Q_RD_DONE_PTR_REG 0x660 1788c2ecf20Sopenharmony_ci#define SEC_Q_CPL_Q_BD_NUM_ST_REG 0x700 1798c2ecf20Sopenharmony_ci#define SEC_Q_CPL_Q_PTR_ST_REG 0x704 1808c2ecf20Sopenharmony_ci#define SEC_Q_CPL_Q_H_ADDR_ST_REG 0x708 1818c2ecf20Sopenharmony_ci#define SEC_Q_CPL_Q_L_ADDR_ST_REG 0x70c 1828c2ecf20Sopenharmony_ci#define SEC_Q_CPL_TASK_INT_NUM_LEFT_ST_REG 0x710 1838c2ecf20Sopenharmony_ci#define SEC_Q_WRR_ID_CHECK_REG 0x714 1848c2ecf20Sopenharmony_ci#define SEC_Q_CPLQ_FULL_CHECK_REG 0x718 1858c2ecf20Sopenharmony_ci#define SEC_Q_SUCCESS_BD_CNT_REG 0x800 1868c2ecf20Sopenharmony_ci#define SEC_Q_FAIL_BD_CNT_REG 0x804 1878c2ecf20Sopenharmony_ci#define SEC_Q_GET_BD_CNT_REG 0x808 1888c2ecf20Sopenharmony_ci#define SEC_Q_IVLD_CNT_REG 0x80c 1898c2ecf20Sopenharmony_ci#define SEC_Q_BD_PROC_GET_CNT_REG 0x810 1908c2ecf20Sopenharmony_ci#define SEC_Q_BD_PROC_DONE_CNT_REG 0x814 1918c2ecf20Sopenharmony_ci#define SEC_Q_LAT_CLR_REG 0x850 1928c2ecf20Sopenharmony_ci#define SEC_Q_PKT_LAT_MAX_REG 0x854 1938c2ecf20Sopenharmony_ci#define SEC_Q_PKT_LAT_AVG_REG 0x858 1948c2ecf20Sopenharmony_ci#define SEC_Q_PKT_LAT_MIN_REG 0x85c 1958c2ecf20Sopenharmony_ci#define SEC_Q_ID_CLR_CFG_REG 0x900 1968c2ecf20Sopenharmony_ci#define SEC_Q_1ST_BD_ERR_ID_REG 0x904 1978c2ecf20Sopenharmony_ci#define SEC_Q_1ST_AUTH_FAIL_ID_REG 0x908 1988c2ecf20Sopenharmony_ci#define SEC_Q_1ST_RD_ERR_ID_REG 0x90c 1998c2ecf20Sopenharmony_ci#define SEC_Q_1ST_ECC2_ERR_ID_REG 0x910 2008c2ecf20Sopenharmony_ci#define SEC_Q_1ST_IVLD_ID_REG 0x914 2018c2ecf20Sopenharmony_ci#define SEC_Q_1ST_BD_WR_ERR_ID_REG 0x918 2028c2ecf20Sopenharmony_ci#define SEC_Q_1ST_ERR_BD_WR_ERR_ID_REG 0x91c 2038c2ecf20Sopenharmony_ci#define SEC_Q_1ST_BD_MAC_WR_ERR_ID_REG 0x920 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistruct sec_debug_bd_info { 2068c2ecf20Sopenharmony_ci#define SEC_DEBUG_BD_INFO_SOFT_ERR_CHECK_M GENMASK(22, 0) 2078c2ecf20Sopenharmony_ci u32 soft_err_check; 2088c2ecf20Sopenharmony_ci#define SEC_DEBUG_BD_INFO_HARD_ERR_CHECK_M GENMASK(9, 0) 2098c2ecf20Sopenharmony_ci u32 hard_err_check; 2108c2ecf20Sopenharmony_ci u32 icv_mac1st_word; 2118c2ecf20Sopenharmony_ci#define SEC_DEBUG_BD_INFO_GET_ID_M GENMASK(19, 0) 2128c2ecf20Sopenharmony_ci u32 sec_get_id; 2138c2ecf20Sopenharmony_ci /* W4---W15 */ 2148c2ecf20Sopenharmony_ci u32 reserv_left[12]; 2158c2ecf20Sopenharmony_ci}; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistruct sec_out_bd_info { 2188c2ecf20Sopenharmony_ci#define SEC_OUT_BD_INFO_Q_ID_M GENMASK(11, 0) 2198c2ecf20Sopenharmony_ci#define SEC_OUT_BD_INFO_ECC_2BIT_ERR BIT(14) 2208c2ecf20Sopenharmony_ci u16 data; 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci#define SEC_MAX_DEVICES 8 2248c2ecf20Sopenharmony_cistatic struct sec_dev_info *sec_devices[SEC_MAX_DEVICES]; 2258c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(sec_id_lock); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int sec_queue_map_io(struct sec_queue *queue) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct device *dev = queue->dev_info->dev; 2308c2ecf20Sopenharmony_ci struct resource *res; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci res = platform_get_resource(to_platform_device(dev), 2338c2ecf20Sopenharmony_ci IORESOURCE_MEM, 2348c2ecf20Sopenharmony_ci 2 + queue->queue_id); 2358c2ecf20Sopenharmony_ci if (!res) { 2368c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get queue %d memory resource\n", 2378c2ecf20Sopenharmony_ci queue->queue_id); 2388c2ecf20Sopenharmony_ci return -ENOMEM; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci queue->regs = ioremap(res->start, resource_size(res)); 2418c2ecf20Sopenharmony_ci if (!queue->regs) 2428c2ecf20Sopenharmony_ci return -ENOMEM; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci return 0; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic void sec_queue_unmap_io(struct sec_queue *queue) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci iounmap(queue->regs); 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic int sec_queue_ar_pkgattr(struct sec_queue *queue, u32 ar_pkg) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci void __iomem *addr = queue->regs + SEC_Q_ARUSER_CFG_REG; 2558c2ecf20Sopenharmony_ci u32 regval; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 2588c2ecf20Sopenharmony_ci if (ar_pkg) 2598c2ecf20Sopenharmony_ci regval |= SEC_Q_ARUSER_CFG_PKG; 2608c2ecf20Sopenharmony_ci else 2618c2ecf20Sopenharmony_ci regval &= ~SEC_Q_ARUSER_CFG_PKG; 2628c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci return 0; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic int sec_queue_aw_pkgattr(struct sec_queue *queue, u32 aw_pkg) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci void __iomem *addr = queue->regs + SEC_Q_AWUSER_CFG_REG; 2708c2ecf20Sopenharmony_ci u32 regval; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 2738c2ecf20Sopenharmony_ci regval |= SEC_Q_AWUSER_CFG_PKG; 2748c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci return 0; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic int sec_clk_en(struct sec_dev_info *info) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci void __iomem *base = info->regs[SEC_COMMON]; 2828c2ecf20Sopenharmony_ci u32 i = 0; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci writel_relaxed(0x7, base + SEC_ALGSUB_CLK_EN_REG); 2858c2ecf20Sopenharmony_ci do { 2868c2ecf20Sopenharmony_ci usleep_range(1000, 10000); 2878c2ecf20Sopenharmony_ci if ((readl_relaxed(base + SEC_ALGSUB_CLK_ST_REG) & 0x7) == 0x7) 2888c2ecf20Sopenharmony_ci return 0; 2898c2ecf20Sopenharmony_ci i++; 2908c2ecf20Sopenharmony_ci } while (i < 10); 2918c2ecf20Sopenharmony_ci dev_err(info->dev, "sec clock enable fail!\n"); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci return -EIO; 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic int sec_clk_dis(struct sec_dev_info *info) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci void __iomem *base = info->regs[SEC_COMMON]; 2998c2ecf20Sopenharmony_ci u32 i = 0; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci writel_relaxed(0x7, base + SEC_ALGSUB_CLK_DIS_REG); 3028c2ecf20Sopenharmony_ci do { 3038c2ecf20Sopenharmony_ci usleep_range(1000, 10000); 3048c2ecf20Sopenharmony_ci if ((readl_relaxed(base + SEC_ALGSUB_CLK_ST_REG) & 0x7) == 0) 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci i++; 3078c2ecf20Sopenharmony_ci } while (i < 10); 3088c2ecf20Sopenharmony_ci dev_err(info->dev, "sec clock disable fail!\n"); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci return -EIO; 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic int sec_reset_whole_module(struct sec_dev_info *info) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci void __iomem *base = info->regs[SEC_COMMON]; 3168c2ecf20Sopenharmony_ci bool is_reset, b_is_reset; 3178c2ecf20Sopenharmony_ci u32 i = 0; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci writel_relaxed(1, base + SEC_ALGSUB_RST_REQ_REG); 3208c2ecf20Sopenharmony_ci writel_relaxed(1, base + SEC_ALGSUB_BUILD_RST_REQ_REG); 3218c2ecf20Sopenharmony_ci while (1) { 3228c2ecf20Sopenharmony_ci usleep_range(1000, 10000); 3238c2ecf20Sopenharmony_ci is_reset = readl_relaxed(base + SEC_ALGSUB_RST_ST_REG) & 3248c2ecf20Sopenharmony_ci SEC_ALGSUB_RST_ST_IS_RST; 3258c2ecf20Sopenharmony_ci b_is_reset = readl_relaxed(base + SEC_ALGSUB_BUILD_RST_ST_REG) & 3268c2ecf20Sopenharmony_ci SEC_ALGSUB_BUILD_RST_ST_IS_RST; 3278c2ecf20Sopenharmony_ci if (is_reset && b_is_reset) 3288c2ecf20Sopenharmony_ci break; 3298c2ecf20Sopenharmony_ci i++; 3308c2ecf20Sopenharmony_ci if (i > 10) { 3318c2ecf20Sopenharmony_ci dev_err(info->dev, "Reset req failed\n"); 3328c2ecf20Sopenharmony_ci return -EIO; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci i = 0; 3378c2ecf20Sopenharmony_ci writel_relaxed(1, base + SEC_ALGSUB_RST_DREQ_REG); 3388c2ecf20Sopenharmony_ci writel_relaxed(1, base + SEC_ALGSUB_BUILD_RST_DREQ_REG); 3398c2ecf20Sopenharmony_ci while (1) { 3408c2ecf20Sopenharmony_ci usleep_range(1000, 10000); 3418c2ecf20Sopenharmony_ci is_reset = readl_relaxed(base + SEC_ALGSUB_RST_ST_REG) & 3428c2ecf20Sopenharmony_ci SEC_ALGSUB_RST_ST_IS_RST; 3438c2ecf20Sopenharmony_ci b_is_reset = readl_relaxed(base + SEC_ALGSUB_BUILD_RST_ST_REG) & 3448c2ecf20Sopenharmony_ci SEC_ALGSUB_BUILD_RST_ST_IS_RST; 3458c2ecf20Sopenharmony_ci if (!is_reset && !b_is_reset) 3468c2ecf20Sopenharmony_ci break; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci i++; 3498c2ecf20Sopenharmony_ci if (i > 10) { 3508c2ecf20Sopenharmony_ci dev_err(info->dev, "Reset dreq failed\n"); 3518c2ecf20Sopenharmony_ci return -EIO; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci return 0; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic void sec_bd_endian_little(struct sec_dev_info *info) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; 3618c2ecf20Sopenharmony_ci u32 regval; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 3648c2ecf20Sopenharmony_ci regval &= ~(SEC_CTRL2_ENDIAN_BD | SEC_CTRL2_ENDIAN_BD_TYPE); 3658c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci/* 3698c2ecf20Sopenharmony_ci * sec_cache_config - configure optimum cache placement 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_cistatic void sec_cache_config(struct sec_dev_info *info) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci struct iommu_domain *domain; 3748c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL_REG; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci domain = iommu_get_domain_for_dev(info->dev); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* Check that translation is occurring */ 3798c2ecf20Sopenharmony_ci if (domain && (domain->type & __IOMMU_DOMAIN_PAGING)) 3808c2ecf20Sopenharmony_ci writel_relaxed(0x44cf9e, addr); 3818c2ecf20Sopenharmony_ci else 3828c2ecf20Sopenharmony_ci writel_relaxed(0x4cfd9, addr); 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic void sec_data_axiwr_otsd_cfg(struct sec_dev_info *info, u32 cfg) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; 3888c2ecf20Sopenharmony_ci u32 regval; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 3918c2ecf20Sopenharmony_ci regval &= ~SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_M; 3928c2ecf20Sopenharmony_ci regval |= (cfg << SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_S) & 3938c2ecf20Sopenharmony_ci SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_M; 3948c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic void sec_data_axird_otsd_cfg(struct sec_dev_info *info, u32 cfg) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; 4008c2ecf20Sopenharmony_ci u32 regval; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 4038c2ecf20Sopenharmony_ci regval &= ~SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_M; 4048c2ecf20Sopenharmony_ci regval |= (cfg << SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_S) & 4058c2ecf20Sopenharmony_ci SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_M; 4068c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic void sec_clk_gate_en(struct sec_dev_info *info, bool clkgate) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; 4128c2ecf20Sopenharmony_ci u32 regval; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 4158c2ecf20Sopenharmony_ci if (clkgate) 4168c2ecf20Sopenharmony_ci regval |= SEC_CTRL2_CLK_GATE_EN; 4178c2ecf20Sopenharmony_ci else 4188c2ecf20Sopenharmony_ci regval &= ~SEC_CTRL2_CLK_GATE_EN; 4198c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic void sec_comm_cnt_cfg(struct sec_dev_info *info, bool clr_ce) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_COMMON_CNT_CLR_CE_REG; 4258c2ecf20Sopenharmony_ci u32 regval; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 4288c2ecf20Sopenharmony_ci if (clr_ce) 4298c2ecf20Sopenharmony_ci regval |= SEC_COMMON_CNT_CLR_CE_CLEAR; 4308c2ecf20Sopenharmony_ci else 4318c2ecf20Sopenharmony_ci regval &= ~SEC_COMMON_CNT_CLR_CE_CLEAR; 4328c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic void sec_commsnap_en(struct sec_dev_info *info, bool snap_en) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_COMMON_CNT_CLR_CE_REG; 4388c2ecf20Sopenharmony_ci u32 regval; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 4418c2ecf20Sopenharmony_ci if (snap_en) 4428c2ecf20Sopenharmony_ci regval |= SEC_COMMON_CNT_CLR_CE_SNAP_EN; 4438c2ecf20Sopenharmony_ci else 4448c2ecf20Sopenharmony_ci regval &= ~SEC_COMMON_CNT_CLR_CE_SNAP_EN; 4458c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic void sec_ipv6_hashmask(struct sec_dev_info *info, u32 hash_mask[]) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci void __iomem *base = info->regs[SEC_SAA]; 4518c2ecf20Sopenharmony_ci int i; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) 4548c2ecf20Sopenharmony_ci writel_relaxed(hash_mask[0], 4558c2ecf20Sopenharmony_ci base + SEC_IPV6_MASK_TABLE_X_REG(i)); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic int sec_ipv4_hashmask(struct sec_dev_info *info, u32 hash_mask) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci if (hash_mask & SEC_HASH_IPV4_MASK) { 4618c2ecf20Sopenharmony_ci dev_err(info->dev, "Sec Ipv4 Hash Mask Input Error!\n "); 4628c2ecf20Sopenharmony_ci return -EINVAL; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci writel_relaxed(hash_mask, 4668c2ecf20Sopenharmony_ci info->regs[SEC_SAA] + SEC_IPV4_MASK_TABLE_REG); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci return 0; 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cistatic void sec_set_dbg_bd_cfg(struct sec_dev_info *info, u32 cfg) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_DEBUG_BD_CFG_REG; 4748c2ecf20Sopenharmony_ci u32 regval; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 4778c2ecf20Sopenharmony_ci /* Always disable write back of normal bd */ 4788c2ecf20Sopenharmony_ci regval &= ~SEC_DEBUG_BD_CFG_WB_NORMAL; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (cfg) 4818c2ecf20Sopenharmony_ci regval &= ~SEC_DEBUG_BD_CFG_WB_EN; 4828c2ecf20Sopenharmony_ci else 4838c2ecf20Sopenharmony_ci regval |= SEC_DEBUG_BD_CFG_WB_EN; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic void sec_saa_getqm_en(struct sec_dev_info *info, u32 saa_indx, u32 en) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci void __iomem *addr = info->regs[SEC_SAA] + SEC_SAA_BASE + 4918c2ecf20Sopenharmony_ci SEC_SAA_CTRL_REG(saa_indx); 4928c2ecf20Sopenharmony_ci u32 regval; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 4958c2ecf20Sopenharmony_ci if (en) 4968c2ecf20Sopenharmony_ci regval |= SEC_SAA_CTRL_GET_QM_EN; 4978c2ecf20Sopenharmony_ci else 4988c2ecf20Sopenharmony_ci regval &= ~SEC_SAA_CTRL_GET_QM_EN; 4998c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic void sec_saa_int_mask(struct sec_dev_info *info, u32 saa_indx, 5038c2ecf20Sopenharmony_ci u32 saa_int_mask) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci writel_relaxed(saa_int_mask, 5068c2ecf20Sopenharmony_ci info->regs[SEC_SAA] + SEC_SAA_BASE + SEC_ST_INTMSK1_REG + 5078c2ecf20Sopenharmony_ci saa_indx * SEC_SAA_ADDR_SIZE); 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic void sec_streamid(struct sec_dev_info *info, int i) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci #define SEC_SID 0x600 5138c2ecf20Sopenharmony_ci #define SEC_VMID 0 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci writel_relaxed((SEC_VMID | ((SEC_SID & 0xffff) << 8)), 5168c2ecf20Sopenharmony_ci info->regs[SEC_SAA] + SEC_Q_VMID_CFG_REG(i)); 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cistatic void sec_queue_ar_alloc(struct sec_queue *queue, u32 alloc) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci void __iomem *addr = queue->regs + SEC_Q_ARUSER_CFG_REG; 5228c2ecf20Sopenharmony_ci u32 regval; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 5258c2ecf20Sopenharmony_ci if (alloc == SEC_QUEUE_AR_FROCE_ALLOC) { 5268c2ecf20Sopenharmony_ci regval |= SEC_Q_ARUSER_CFG_FA; 5278c2ecf20Sopenharmony_ci regval &= ~SEC_Q_ARUSER_CFG_FNA; 5288c2ecf20Sopenharmony_ci } else { 5298c2ecf20Sopenharmony_ci regval &= ~SEC_Q_ARUSER_CFG_FA; 5308c2ecf20Sopenharmony_ci regval |= SEC_Q_ARUSER_CFG_FNA; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic void sec_queue_aw_alloc(struct sec_queue *queue, u32 alloc) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci void __iomem *addr = queue->regs + SEC_Q_AWUSER_CFG_REG; 5398c2ecf20Sopenharmony_ci u32 regval; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 5428c2ecf20Sopenharmony_ci if (alloc == SEC_QUEUE_AW_FROCE_ALLOC) { 5438c2ecf20Sopenharmony_ci regval |= SEC_Q_AWUSER_CFG_FA; 5448c2ecf20Sopenharmony_ci regval &= ~SEC_Q_AWUSER_CFG_FNA; 5458c2ecf20Sopenharmony_ci } else { 5468c2ecf20Sopenharmony_ci regval &= ~SEC_Q_AWUSER_CFG_FA; 5478c2ecf20Sopenharmony_ci regval |= SEC_Q_AWUSER_CFG_FNA; 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic void sec_queue_reorder(struct sec_queue *queue, bool reorder) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci void __iomem *base = queue->regs; 5568c2ecf20Sopenharmony_ci u32 regval; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci regval = readl_relaxed(base + SEC_Q_CFG_REG); 5598c2ecf20Sopenharmony_ci if (reorder) 5608c2ecf20Sopenharmony_ci regval |= SEC_Q_CFG_REORDER; 5618c2ecf20Sopenharmony_ci else 5628c2ecf20Sopenharmony_ci regval &= ~SEC_Q_CFG_REORDER; 5638c2ecf20Sopenharmony_ci writel_relaxed(regval, base + SEC_Q_CFG_REG); 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic void sec_queue_depth(struct sec_queue *queue, u32 depth) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci void __iomem *addr = queue->regs + SEC_Q_DEPTH_CFG_REG; 5698c2ecf20Sopenharmony_ci u32 regval; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci regval = readl_relaxed(addr); 5728c2ecf20Sopenharmony_ci regval &= ~SEC_Q_DEPTH_CFG_DEPTH_M; 5738c2ecf20Sopenharmony_ci regval |= (depth << SEC_Q_DEPTH_CFG_DEPTH_S) & SEC_Q_DEPTH_CFG_DEPTH_M; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci writel_relaxed(regval, addr); 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic void sec_queue_cmdbase_addr(struct sec_queue *queue, u64 addr) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci writel_relaxed(upper_32_bits(addr), queue->regs + SEC_Q_BASE_HADDR_REG); 5818c2ecf20Sopenharmony_ci writel_relaxed(lower_32_bits(addr), queue->regs + SEC_Q_BASE_LADDR_REG); 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic void sec_queue_outorder_addr(struct sec_queue *queue, u64 addr) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci writel_relaxed(upper_32_bits(addr), 5878c2ecf20Sopenharmony_ci queue->regs + SEC_Q_OUTORDER_BASE_HADDR_REG); 5888c2ecf20Sopenharmony_ci writel_relaxed(lower_32_bits(addr), 5898c2ecf20Sopenharmony_ci queue->regs + SEC_Q_OUTORDER_BASE_LADDR_REG); 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_cistatic void sec_queue_errbase_addr(struct sec_queue *queue, u64 addr) 5938c2ecf20Sopenharmony_ci{ 5948c2ecf20Sopenharmony_ci writel_relaxed(upper_32_bits(addr), 5958c2ecf20Sopenharmony_ci queue->regs + SEC_Q_ERR_BASE_HADDR_REG); 5968c2ecf20Sopenharmony_ci writel_relaxed(lower_32_bits(addr), 5978c2ecf20Sopenharmony_ci queue->regs + SEC_Q_ERR_BASE_LADDR_REG); 5988c2ecf20Sopenharmony_ci} 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_cistatic void sec_queue_irq_disable(struct sec_queue *queue) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci writel_relaxed((u32)~0, queue->regs + SEC_Q_FLOW_INT_MKS_REG); 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cistatic void sec_queue_irq_enable(struct sec_queue *queue) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci writel_relaxed(0, queue->regs + SEC_Q_FLOW_INT_MKS_REG); 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_cistatic void sec_queue_abn_irq_disable(struct sec_queue *queue) 6118c2ecf20Sopenharmony_ci{ 6128c2ecf20Sopenharmony_ci writel_relaxed((u32)~0, queue->regs + SEC_Q_FAIL_INT_MSK_REG); 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_cistatic void sec_queue_stop(struct sec_queue *queue) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci disable_irq(queue->task_irq); 6188c2ecf20Sopenharmony_ci sec_queue_irq_disable(queue); 6198c2ecf20Sopenharmony_ci writel_relaxed(0x0, queue->regs + SEC_QUEUE_ENB_REG); 6208c2ecf20Sopenharmony_ci} 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cistatic void sec_queue_start(struct sec_queue *queue) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci sec_queue_irq_enable(queue); 6258c2ecf20Sopenharmony_ci enable_irq(queue->task_irq); 6268c2ecf20Sopenharmony_ci queue->expected = 0; 6278c2ecf20Sopenharmony_ci writel_relaxed(SEC_Q_INIT_AND_STAT_CLEAR, queue->regs + SEC_Q_INIT_REG); 6288c2ecf20Sopenharmony_ci writel_relaxed(0x1, queue->regs + SEC_QUEUE_ENB_REG); 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic struct sec_queue *sec_alloc_queue(struct sec_dev_info *info) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci int i; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci mutex_lock(&info->dev_lock); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci /* Get the first idle queue in SEC device */ 6388c2ecf20Sopenharmony_ci for (i = 0; i < SEC_Q_NUM; i++) 6398c2ecf20Sopenharmony_ci if (!info->queues[i].in_use) { 6408c2ecf20Sopenharmony_ci info->queues[i].in_use = true; 6418c2ecf20Sopenharmony_ci info->queues_in_use++; 6428c2ecf20Sopenharmony_ci mutex_unlock(&info->dev_lock); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci return &info->queues[i]; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci mutex_unlock(&info->dev_lock); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci return ERR_PTR(-ENODEV); 6498c2ecf20Sopenharmony_ci} 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_cistatic int sec_queue_free(struct sec_queue *queue) 6528c2ecf20Sopenharmony_ci{ 6538c2ecf20Sopenharmony_ci struct sec_dev_info *info = queue->dev_info; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci if (queue->queue_id >= SEC_Q_NUM) { 6568c2ecf20Sopenharmony_ci dev_err(info->dev, "No queue %d\n", queue->queue_id); 6578c2ecf20Sopenharmony_ci return -ENODEV; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci if (!queue->in_use) { 6618c2ecf20Sopenharmony_ci dev_err(info->dev, "Queue %d is idle\n", queue->queue_id); 6628c2ecf20Sopenharmony_ci return -ENODEV; 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci mutex_lock(&info->dev_lock); 6668c2ecf20Sopenharmony_ci queue->in_use = false; 6678c2ecf20Sopenharmony_ci info->queues_in_use--; 6688c2ecf20Sopenharmony_ci mutex_unlock(&info->dev_lock); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci return 0; 6718c2ecf20Sopenharmony_ci} 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_cistatic irqreturn_t sec_isr_handle_th(int irq, void *q) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci sec_queue_irq_disable(q); 6768c2ecf20Sopenharmony_ci return IRQ_WAKE_THREAD; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic irqreturn_t sec_isr_handle(int irq, void *q) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci struct sec_queue *queue = q; 6828c2ecf20Sopenharmony_ci struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; 6838c2ecf20Sopenharmony_ci struct sec_queue_ring_cq *cq_ring = &queue->ring_cq; 6848c2ecf20Sopenharmony_ci struct sec_out_bd_info *outorder_msg; 6858c2ecf20Sopenharmony_ci struct sec_bd_info *msg; 6868c2ecf20Sopenharmony_ci u32 ooo_read, ooo_write; 6878c2ecf20Sopenharmony_ci void __iomem *base = queue->regs; 6888c2ecf20Sopenharmony_ci int q_id; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci ooo_read = readl(base + SEC_Q_OUTORDER_RD_PTR_REG); 6918c2ecf20Sopenharmony_ci ooo_write = readl(base + SEC_Q_OUTORDER_WR_PTR_REG); 6928c2ecf20Sopenharmony_ci outorder_msg = cq_ring->vaddr + ooo_read; 6938c2ecf20Sopenharmony_ci q_id = outorder_msg->data & SEC_OUT_BD_INFO_Q_ID_M; 6948c2ecf20Sopenharmony_ci msg = msg_ring->vaddr + q_id; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci while ((ooo_write != ooo_read) && msg->w0 & SEC_BD_W0_DONE) { 6978c2ecf20Sopenharmony_ci /* 6988c2ecf20Sopenharmony_ci * Must be before callback otherwise blocks adding other chained 6998c2ecf20Sopenharmony_ci * elements 7008c2ecf20Sopenharmony_ci */ 7018c2ecf20Sopenharmony_ci set_bit(q_id, queue->unprocessed); 7028c2ecf20Sopenharmony_ci if (q_id == queue->expected) 7038c2ecf20Sopenharmony_ci while (test_bit(queue->expected, queue->unprocessed)) { 7048c2ecf20Sopenharmony_ci clear_bit(queue->expected, queue->unprocessed); 7058c2ecf20Sopenharmony_ci msg = msg_ring->vaddr + queue->expected; 7068c2ecf20Sopenharmony_ci msg->w0 &= ~SEC_BD_W0_DONE; 7078c2ecf20Sopenharmony_ci msg_ring->callback(msg, 7088c2ecf20Sopenharmony_ci queue->shadow[queue->expected]); 7098c2ecf20Sopenharmony_ci queue->shadow[queue->expected] = NULL; 7108c2ecf20Sopenharmony_ci queue->expected = (queue->expected + 1) % 7118c2ecf20Sopenharmony_ci SEC_QUEUE_LEN; 7128c2ecf20Sopenharmony_ci atomic_dec(&msg_ring->used); 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci ooo_read = (ooo_read + 1) % SEC_QUEUE_LEN; 7168c2ecf20Sopenharmony_ci writel(ooo_read, base + SEC_Q_OUTORDER_RD_PTR_REG); 7178c2ecf20Sopenharmony_ci ooo_write = readl(base + SEC_Q_OUTORDER_WR_PTR_REG); 7188c2ecf20Sopenharmony_ci outorder_msg = cq_ring->vaddr + ooo_read; 7198c2ecf20Sopenharmony_ci q_id = outorder_msg->data & SEC_OUT_BD_INFO_Q_ID_M; 7208c2ecf20Sopenharmony_ci msg = msg_ring->vaddr + q_id; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci sec_queue_irq_enable(queue); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci return IRQ_HANDLED; 7268c2ecf20Sopenharmony_ci} 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_cistatic int sec_queue_irq_init(struct sec_queue *queue) 7298c2ecf20Sopenharmony_ci{ 7308c2ecf20Sopenharmony_ci struct sec_dev_info *info = queue->dev_info; 7318c2ecf20Sopenharmony_ci int irq = queue->task_irq; 7328c2ecf20Sopenharmony_ci int ret; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci ret = request_threaded_irq(irq, sec_isr_handle_th, sec_isr_handle, 7358c2ecf20Sopenharmony_ci IRQF_TRIGGER_RISING, queue->name, queue); 7368c2ecf20Sopenharmony_ci if (ret) { 7378c2ecf20Sopenharmony_ci dev_err(info->dev, "request irq(%d) failed %d\n", irq, ret); 7388c2ecf20Sopenharmony_ci return ret; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci disable_irq(irq); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci return 0; 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic int sec_queue_irq_uninit(struct sec_queue *queue) 7468c2ecf20Sopenharmony_ci{ 7478c2ecf20Sopenharmony_ci free_irq(queue->task_irq, queue); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci return 0; 7508c2ecf20Sopenharmony_ci} 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_cistatic struct sec_dev_info *sec_device_get(void) 7538c2ecf20Sopenharmony_ci{ 7548c2ecf20Sopenharmony_ci struct sec_dev_info *sec_dev = NULL; 7558c2ecf20Sopenharmony_ci struct sec_dev_info *this_sec_dev; 7568c2ecf20Sopenharmony_ci int least_busy_n = SEC_Q_NUM + 1; 7578c2ecf20Sopenharmony_ci int i; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* Find which one is least busy and use that first */ 7608c2ecf20Sopenharmony_ci for (i = 0; i < SEC_MAX_DEVICES; i++) { 7618c2ecf20Sopenharmony_ci this_sec_dev = sec_devices[i]; 7628c2ecf20Sopenharmony_ci if (this_sec_dev && 7638c2ecf20Sopenharmony_ci this_sec_dev->queues_in_use < least_busy_n) { 7648c2ecf20Sopenharmony_ci least_busy_n = this_sec_dev->queues_in_use; 7658c2ecf20Sopenharmony_ci sec_dev = this_sec_dev; 7668c2ecf20Sopenharmony_ci } 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci return sec_dev; 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_cistatic struct sec_queue *sec_queue_alloc_start(struct sec_dev_info *info) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci struct sec_queue *queue; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci queue = sec_alloc_queue(info); 7778c2ecf20Sopenharmony_ci if (IS_ERR(queue)) { 7788c2ecf20Sopenharmony_ci dev_err(info->dev, "alloc sec queue failed! %ld\n", 7798c2ecf20Sopenharmony_ci PTR_ERR(queue)); 7808c2ecf20Sopenharmony_ci return queue; 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci sec_queue_start(queue); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci return queue; 7868c2ecf20Sopenharmony_ci} 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci/** 7898c2ecf20Sopenharmony_ci * sec_queue_alloc_start_safe - get a hw queue from appropriate instance 7908c2ecf20Sopenharmony_ci * 7918c2ecf20Sopenharmony_ci * This function does extremely simplistic load balancing. It does not take into 7928c2ecf20Sopenharmony_ci * account NUMA locality of the accelerator, or which cpu has requested the 7938c2ecf20Sopenharmony_ci * queue. Future work may focus on optimizing this in order to improve full 7948c2ecf20Sopenharmony_ci * machine throughput. 7958c2ecf20Sopenharmony_ci */ 7968c2ecf20Sopenharmony_cistruct sec_queue *sec_queue_alloc_start_safe(void) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci struct sec_dev_info *info; 7998c2ecf20Sopenharmony_ci struct sec_queue *queue = ERR_PTR(-ENODEV); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci mutex_lock(&sec_id_lock); 8028c2ecf20Sopenharmony_ci info = sec_device_get(); 8038c2ecf20Sopenharmony_ci if (!info) 8048c2ecf20Sopenharmony_ci goto unlock; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci queue = sec_queue_alloc_start(info); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ciunlock: 8098c2ecf20Sopenharmony_ci mutex_unlock(&sec_id_lock); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return queue; 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci/** 8158c2ecf20Sopenharmony_ci * sec_queue_stop_release() - free up a hw queue for reuse 8168c2ecf20Sopenharmony_ci * @queue: The queue we are done with. 8178c2ecf20Sopenharmony_ci * 8188c2ecf20Sopenharmony_ci * This will stop the current queue, terminanting any transactions 8198c2ecf20Sopenharmony_ci * that are inflight an return it to the pool of available hw queuess 8208c2ecf20Sopenharmony_ci */ 8218c2ecf20Sopenharmony_ciint sec_queue_stop_release(struct sec_queue *queue) 8228c2ecf20Sopenharmony_ci{ 8238c2ecf20Sopenharmony_ci struct device *dev = queue->dev_info->dev; 8248c2ecf20Sopenharmony_ci int ret; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci sec_queue_stop(queue); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci ret = sec_queue_free(queue); 8298c2ecf20Sopenharmony_ci if (ret) 8308c2ecf20Sopenharmony_ci dev_err(dev, "Releasing queue failed %d\n", ret); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci return ret; 8338c2ecf20Sopenharmony_ci} 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci/** 8368c2ecf20Sopenharmony_ci * sec_queue_empty() - Is this hardware queue currently empty. 8378c2ecf20Sopenharmony_ci * 8388c2ecf20Sopenharmony_ci * We need to know if we have an empty queue for some of the chaining modes 8398c2ecf20Sopenharmony_ci * as if it is not empty we may need to hold the message in a software queue 8408c2ecf20Sopenharmony_ci * until the hw queue is drained. 8418c2ecf20Sopenharmony_ci */ 8428c2ecf20Sopenharmony_cibool sec_queue_empty(struct sec_queue *queue) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci return !atomic_read(&msg_ring->used); 8478c2ecf20Sopenharmony_ci} 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci/** 8508c2ecf20Sopenharmony_ci * sec_queue_send() - queue up a single operation in the hw queue 8518c2ecf20Sopenharmony_ci * @queue: The queue in which to put the message 8528c2ecf20Sopenharmony_ci * @msg: The message 8538c2ecf20Sopenharmony_ci * @ctx: Context to be put in the shadow array and passed back to cb on result. 8548c2ecf20Sopenharmony_ci * 8558c2ecf20Sopenharmony_ci * This function will return -EAGAIN if the queue is currently full. 8568c2ecf20Sopenharmony_ci */ 8578c2ecf20Sopenharmony_ciint sec_queue_send(struct sec_queue *queue, struct sec_bd_info *msg, void *ctx) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; 8608c2ecf20Sopenharmony_ci void __iomem *base = queue->regs; 8618c2ecf20Sopenharmony_ci u32 write, read; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci mutex_lock(&msg_ring->lock); 8648c2ecf20Sopenharmony_ci read = readl(base + SEC_Q_RD_PTR_REG); 8658c2ecf20Sopenharmony_ci write = readl(base + SEC_Q_WR_PTR_REG); 8668c2ecf20Sopenharmony_ci if (write == read && atomic_read(&msg_ring->used) == SEC_QUEUE_LEN) { 8678c2ecf20Sopenharmony_ci mutex_unlock(&msg_ring->lock); 8688c2ecf20Sopenharmony_ci return -EAGAIN; 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci memcpy(msg_ring->vaddr + write, msg, sizeof(*msg)); 8718c2ecf20Sopenharmony_ci queue->shadow[write] = ctx; 8728c2ecf20Sopenharmony_ci write = (write + 1) % SEC_QUEUE_LEN; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci /* Ensure content updated before queue advance */ 8758c2ecf20Sopenharmony_ci wmb(); 8768c2ecf20Sopenharmony_ci writel(write, base + SEC_Q_WR_PTR_REG); 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci atomic_inc(&msg_ring->used); 8798c2ecf20Sopenharmony_ci mutex_unlock(&msg_ring->lock); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci return 0; 8828c2ecf20Sopenharmony_ci} 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_cibool sec_queue_can_enqueue(struct sec_queue *queue, int num) 8858c2ecf20Sopenharmony_ci{ 8868c2ecf20Sopenharmony_ci struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci return SEC_QUEUE_LEN - atomic_read(&msg_ring->used) >= num; 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic void sec_queue_hw_init(struct sec_queue *queue) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci sec_queue_ar_alloc(queue, SEC_QUEUE_AR_FROCE_NOALLOC); 8948c2ecf20Sopenharmony_ci sec_queue_aw_alloc(queue, SEC_QUEUE_AR_FROCE_NOALLOC); 8958c2ecf20Sopenharmony_ci sec_queue_ar_pkgattr(queue, 1); 8968c2ecf20Sopenharmony_ci sec_queue_aw_pkgattr(queue, 1); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci /* Enable out of order queue */ 8998c2ecf20Sopenharmony_ci sec_queue_reorder(queue, true); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci /* Interrupt after a single complete element */ 9028c2ecf20Sopenharmony_ci writel_relaxed(1, queue->regs + SEC_Q_PROC_NUM_CFG_REG); 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci sec_queue_depth(queue, SEC_QUEUE_LEN - 1); 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci sec_queue_cmdbase_addr(queue, queue->ring_cmd.paddr); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci sec_queue_outorder_addr(queue, queue->ring_cq.paddr); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci sec_queue_errbase_addr(queue, queue->ring_db.paddr); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci writel_relaxed(0x100, queue->regs + SEC_Q_OT_TH_REG); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci sec_queue_abn_irq_disable(queue); 9158c2ecf20Sopenharmony_ci sec_queue_irq_disable(queue); 9168c2ecf20Sopenharmony_ci writel_relaxed(SEC_Q_INIT_AND_STAT_CLEAR, queue->regs + SEC_Q_INIT_REG); 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_cistatic int sec_hw_init(struct sec_dev_info *info) 9208c2ecf20Sopenharmony_ci{ 9218c2ecf20Sopenharmony_ci struct iommu_domain *domain; 9228c2ecf20Sopenharmony_ci u32 sec_ipv4_mask = 0; 9238c2ecf20Sopenharmony_ci u32 sec_ipv6_mask[10] = {}; 9248c2ecf20Sopenharmony_ci u32 i, ret; 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci domain = iommu_get_domain_for_dev(info->dev); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci /* 9298c2ecf20Sopenharmony_ci * Enable all available processing unit clocks. 9308c2ecf20Sopenharmony_ci * Only the first cluster is usable with translations. 9318c2ecf20Sopenharmony_ci */ 9328c2ecf20Sopenharmony_ci if (domain && (domain->type & __IOMMU_DOMAIN_PAGING)) 9338c2ecf20Sopenharmony_ci info->num_saas = 5; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci else 9368c2ecf20Sopenharmony_ci info->num_saas = 10; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci writel_relaxed(GENMASK(info->num_saas - 1, 0), 9398c2ecf20Sopenharmony_ci info->regs[SEC_SAA] + SEC_CLK_EN_REG); 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci /* 32 bit little endian */ 9428c2ecf20Sopenharmony_ci sec_bd_endian_little(info); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci sec_cache_config(info); 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci /* Data axi port write and read outstanding config as per datasheet */ 9478c2ecf20Sopenharmony_ci sec_data_axiwr_otsd_cfg(info, 0x7); 9488c2ecf20Sopenharmony_ci sec_data_axird_otsd_cfg(info, 0x7); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci /* Enable clock gating */ 9518c2ecf20Sopenharmony_ci sec_clk_gate_en(info, true); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* Set CNT_CYC register not read clear */ 9548c2ecf20Sopenharmony_ci sec_comm_cnt_cfg(info, false); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci /* Enable CNT_CYC */ 9578c2ecf20Sopenharmony_ci sec_commsnap_en(info, false); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci writel_relaxed((u32)~0, info->regs[SEC_SAA] + SEC_FSM_MAX_CNT_REG); 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci ret = sec_ipv4_hashmask(info, sec_ipv4_mask); 9628c2ecf20Sopenharmony_ci if (ret) { 9638c2ecf20Sopenharmony_ci dev_err(info->dev, "Failed to set ipv4 hashmask %d\n", ret); 9648c2ecf20Sopenharmony_ci return -EIO; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci sec_ipv6_hashmask(info, sec_ipv6_mask); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* do not use debug bd */ 9708c2ecf20Sopenharmony_ci sec_set_dbg_bd_cfg(info, 0); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci if (domain && (domain->type & __IOMMU_DOMAIN_PAGING)) { 9738c2ecf20Sopenharmony_ci for (i = 0; i < SEC_Q_NUM; i++) { 9748c2ecf20Sopenharmony_ci sec_streamid(info, i); 9758c2ecf20Sopenharmony_ci /* Same QoS for all queues */ 9768c2ecf20Sopenharmony_ci writel_relaxed(0x3f, 9778c2ecf20Sopenharmony_ci info->regs[SEC_SAA] + 9788c2ecf20Sopenharmony_ci SEC_Q_WEIGHT_CFG_REG(i)); 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci for (i = 0; i < info->num_saas; i++) { 9838c2ecf20Sopenharmony_ci sec_saa_getqm_en(info, i, 1); 9848c2ecf20Sopenharmony_ci sec_saa_int_mask(info, i, 0); 9858c2ecf20Sopenharmony_ci } 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci return 0; 9888c2ecf20Sopenharmony_ci} 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_cistatic void sec_hw_exit(struct sec_dev_info *info) 9918c2ecf20Sopenharmony_ci{ 9928c2ecf20Sopenharmony_ci int i; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci for (i = 0; i < SEC_MAX_SAA_NUM; i++) { 9958c2ecf20Sopenharmony_ci sec_saa_int_mask(info, i, (u32)~0); 9968c2ecf20Sopenharmony_ci sec_saa_getqm_en(info, i, 0); 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic void sec_queue_base_init(struct sec_dev_info *info, 10018c2ecf20Sopenharmony_ci struct sec_queue *queue, int queue_id) 10028c2ecf20Sopenharmony_ci{ 10038c2ecf20Sopenharmony_ci queue->dev_info = info; 10048c2ecf20Sopenharmony_ci queue->queue_id = queue_id; 10058c2ecf20Sopenharmony_ci snprintf(queue->name, sizeof(queue->name), 10068c2ecf20Sopenharmony_ci "%s_%d", dev_name(info->dev), queue->queue_id); 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic int sec_map_io(struct sec_dev_info *info, struct platform_device *pdev) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci struct resource *res; 10128c2ecf20Sopenharmony_ci int i; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci for (i = 0; i < SEC_NUM_ADDR_REGIONS; i++) { 10158c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, i); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci if (!res) { 10188c2ecf20Sopenharmony_ci dev_err(info->dev, "Memory resource %d not found\n", i); 10198c2ecf20Sopenharmony_ci return -EINVAL; 10208c2ecf20Sopenharmony_ci } 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci info->regs[i] = devm_ioremap(info->dev, res->start, 10238c2ecf20Sopenharmony_ci resource_size(res)); 10248c2ecf20Sopenharmony_ci if (!info->regs[i]) { 10258c2ecf20Sopenharmony_ci dev_err(info->dev, 10268c2ecf20Sopenharmony_ci "Memory resource %d could not be remapped\n", 10278c2ecf20Sopenharmony_ci i); 10288c2ecf20Sopenharmony_ci return -EINVAL; 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci return 0; 10338c2ecf20Sopenharmony_ci} 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_cistatic int sec_base_init(struct sec_dev_info *info, 10368c2ecf20Sopenharmony_ci struct platform_device *pdev) 10378c2ecf20Sopenharmony_ci{ 10388c2ecf20Sopenharmony_ci int ret; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci ret = sec_map_io(info, pdev); 10418c2ecf20Sopenharmony_ci if (ret) 10428c2ecf20Sopenharmony_ci return ret; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci ret = sec_clk_en(info); 10458c2ecf20Sopenharmony_ci if (ret) 10468c2ecf20Sopenharmony_ci return ret; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci ret = sec_reset_whole_module(info); 10498c2ecf20Sopenharmony_ci if (ret) 10508c2ecf20Sopenharmony_ci goto sec_clk_disable; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci ret = sec_hw_init(info); 10538c2ecf20Sopenharmony_ci if (ret) 10548c2ecf20Sopenharmony_ci goto sec_clk_disable; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci return 0; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cisec_clk_disable: 10598c2ecf20Sopenharmony_ci sec_clk_dis(info); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci return ret; 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistatic void sec_base_exit(struct sec_dev_info *info) 10658c2ecf20Sopenharmony_ci{ 10668c2ecf20Sopenharmony_ci sec_hw_exit(info); 10678c2ecf20Sopenharmony_ci sec_clk_dis(info); 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci#define SEC_Q_CMD_SIZE \ 10718c2ecf20Sopenharmony_ci round_up(SEC_QUEUE_LEN * sizeof(struct sec_bd_info), PAGE_SIZE) 10728c2ecf20Sopenharmony_ci#define SEC_Q_CQ_SIZE \ 10738c2ecf20Sopenharmony_ci round_up(SEC_QUEUE_LEN * sizeof(struct sec_out_bd_info), PAGE_SIZE) 10748c2ecf20Sopenharmony_ci#define SEC_Q_DB_SIZE \ 10758c2ecf20Sopenharmony_ci round_up(SEC_QUEUE_LEN * sizeof(struct sec_debug_bd_info), PAGE_SIZE) 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_cistatic int sec_queue_res_cfg(struct sec_queue *queue) 10788c2ecf20Sopenharmony_ci{ 10798c2ecf20Sopenharmony_ci struct device *dev = queue->dev_info->dev; 10808c2ecf20Sopenharmony_ci struct sec_queue_ring_cmd *ring_cmd = &queue->ring_cmd; 10818c2ecf20Sopenharmony_ci struct sec_queue_ring_cq *ring_cq = &queue->ring_cq; 10828c2ecf20Sopenharmony_ci struct sec_queue_ring_db *ring_db = &queue->ring_db; 10838c2ecf20Sopenharmony_ci int ret; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci ring_cmd->vaddr = dma_alloc_coherent(dev, SEC_Q_CMD_SIZE, 10868c2ecf20Sopenharmony_ci &ring_cmd->paddr, GFP_KERNEL); 10878c2ecf20Sopenharmony_ci if (!ring_cmd->vaddr) 10888c2ecf20Sopenharmony_ci return -ENOMEM; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci atomic_set(&ring_cmd->used, 0); 10918c2ecf20Sopenharmony_ci mutex_init(&ring_cmd->lock); 10928c2ecf20Sopenharmony_ci ring_cmd->callback = sec_alg_callback; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci ring_cq->vaddr = dma_alloc_coherent(dev, SEC_Q_CQ_SIZE, 10958c2ecf20Sopenharmony_ci &ring_cq->paddr, GFP_KERNEL); 10968c2ecf20Sopenharmony_ci if (!ring_cq->vaddr) { 10978c2ecf20Sopenharmony_ci ret = -ENOMEM; 10988c2ecf20Sopenharmony_ci goto err_free_ring_cmd; 10998c2ecf20Sopenharmony_ci } 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci ring_db->vaddr = dma_alloc_coherent(dev, SEC_Q_DB_SIZE, 11028c2ecf20Sopenharmony_ci &ring_db->paddr, GFP_KERNEL); 11038c2ecf20Sopenharmony_ci if (!ring_db->vaddr) { 11048c2ecf20Sopenharmony_ci ret = -ENOMEM; 11058c2ecf20Sopenharmony_ci goto err_free_ring_cq; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci queue->task_irq = platform_get_irq(to_platform_device(dev), 11088c2ecf20Sopenharmony_ci queue->queue_id * 2 + 1); 11098c2ecf20Sopenharmony_ci if (queue->task_irq <= 0) { 11108c2ecf20Sopenharmony_ci ret = -EINVAL; 11118c2ecf20Sopenharmony_ci goto err_free_ring_db; 11128c2ecf20Sopenharmony_ci } 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci return 0; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_cierr_free_ring_db: 11178c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_Q_DB_SIZE, queue->ring_db.vaddr, 11188c2ecf20Sopenharmony_ci queue->ring_db.paddr); 11198c2ecf20Sopenharmony_cierr_free_ring_cq: 11208c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_Q_CQ_SIZE, queue->ring_cq.vaddr, 11218c2ecf20Sopenharmony_ci queue->ring_cq.paddr); 11228c2ecf20Sopenharmony_cierr_free_ring_cmd: 11238c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_Q_CMD_SIZE, queue->ring_cmd.vaddr, 11248c2ecf20Sopenharmony_ci queue->ring_cmd.paddr); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci return ret; 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_cistatic void sec_queue_free_ring_pages(struct sec_queue *queue) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci struct device *dev = queue->dev_info->dev; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_Q_DB_SIZE, queue->ring_db.vaddr, 11348c2ecf20Sopenharmony_ci queue->ring_db.paddr); 11358c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_Q_CQ_SIZE, queue->ring_cq.vaddr, 11368c2ecf20Sopenharmony_ci queue->ring_cq.paddr); 11378c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_Q_CMD_SIZE, queue->ring_cmd.vaddr, 11388c2ecf20Sopenharmony_ci queue->ring_cmd.paddr); 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_cistatic int sec_queue_config(struct sec_dev_info *info, struct sec_queue *queue, 11428c2ecf20Sopenharmony_ci int queue_id) 11438c2ecf20Sopenharmony_ci{ 11448c2ecf20Sopenharmony_ci int ret; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci sec_queue_base_init(info, queue, queue_id); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci ret = sec_queue_res_cfg(queue); 11498c2ecf20Sopenharmony_ci if (ret) 11508c2ecf20Sopenharmony_ci return ret; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci ret = sec_queue_map_io(queue); 11538c2ecf20Sopenharmony_ci if (ret) { 11548c2ecf20Sopenharmony_ci dev_err(info->dev, "Queue map failed %d\n", ret); 11558c2ecf20Sopenharmony_ci sec_queue_free_ring_pages(queue); 11568c2ecf20Sopenharmony_ci return ret; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci sec_queue_hw_init(queue); 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci return 0; 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_cistatic void sec_queue_unconfig(struct sec_dev_info *info, 11658c2ecf20Sopenharmony_ci struct sec_queue *queue) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci sec_queue_unmap_io(queue); 11688c2ecf20Sopenharmony_ci sec_queue_free_ring_pages(queue); 11698c2ecf20Sopenharmony_ci} 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_cistatic int sec_id_alloc(struct sec_dev_info *info) 11728c2ecf20Sopenharmony_ci{ 11738c2ecf20Sopenharmony_ci int ret = 0; 11748c2ecf20Sopenharmony_ci int i; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci mutex_lock(&sec_id_lock); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci for (i = 0; i < SEC_MAX_DEVICES; i++) 11798c2ecf20Sopenharmony_ci if (!sec_devices[i]) 11808c2ecf20Sopenharmony_ci break; 11818c2ecf20Sopenharmony_ci if (i == SEC_MAX_DEVICES) { 11828c2ecf20Sopenharmony_ci ret = -ENOMEM; 11838c2ecf20Sopenharmony_ci goto unlock; 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci info->sec_id = i; 11868c2ecf20Sopenharmony_ci sec_devices[info->sec_id] = info; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ciunlock: 11898c2ecf20Sopenharmony_ci mutex_unlock(&sec_id_lock); 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci return ret; 11928c2ecf20Sopenharmony_ci} 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_cistatic void sec_id_free(struct sec_dev_info *info) 11958c2ecf20Sopenharmony_ci{ 11968c2ecf20Sopenharmony_ci mutex_lock(&sec_id_lock); 11978c2ecf20Sopenharmony_ci sec_devices[info->sec_id] = NULL; 11988c2ecf20Sopenharmony_ci mutex_unlock(&sec_id_lock); 11998c2ecf20Sopenharmony_ci} 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_cistatic int sec_probe(struct platform_device *pdev) 12028c2ecf20Sopenharmony_ci{ 12038c2ecf20Sopenharmony_ci struct sec_dev_info *info; 12048c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 12058c2ecf20Sopenharmony_ci int i, j; 12068c2ecf20Sopenharmony_ci int ret; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 12098c2ecf20Sopenharmony_ci if (ret) { 12108c2ecf20Sopenharmony_ci dev_err(dev, "Failed to set 64 bit dma mask %d", ret); 12118c2ecf20Sopenharmony_ci return -ENODEV; 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci info = devm_kzalloc(dev, (sizeof(*info)), GFP_KERNEL); 12158c2ecf20Sopenharmony_ci if (!info) 12168c2ecf20Sopenharmony_ci return -ENOMEM; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci info->dev = dev; 12198c2ecf20Sopenharmony_ci mutex_init(&info->dev_lock); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci info->hw_sgl_pool = dmam_pool_create("sgl", dev, 12228c2ecf20Sopenharmony_ci sizeof(struct sec_hw_sgl), 64, 0); 12238c2ecf20Sopenharmony_ci if (!info->hw_sgl_pool) { 12248c2ecf20Sopenharmony_ci dev_err(dev, "Failed to create sec sgl dma pool\n"); 12258c2ecf20Sopenharmony_ci return -ENOMEM; 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci ret = sec_base_init(info, pdev); 12298c2ecf20Sopenharmony_ci if (ret) { 12308c2ecf20Sopenharmony_ci dev_err(dev, "Base initialization fail! %d\n", ret); 12318c2ecf20Sopenharmony_ci return ret; 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci for (i = 0; i < SEC_Q_NUM; i++) { 12358c2ecf20Sopenharmony_ci ret = sec_queue_config(info, &info->queues[i], i); 12368c2ecf20Sopenharmony_ci if (ret) 12378c2ecf20Sopenharmony_ci goto queues_unconfig; 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci ret = sec_queue_irq_init(&info->queues[i]); 12408c2ecf20Sopenharmony_ci if (ret) { 12418c2ecf20Sopenharmony_ci sec_queue_unconfig(info, &info->queues[i]); 12428c2ecf20Sopenharmony_ci goto queues_unconfig; 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci ret = sec_algs_register(); 12478c2ecf20Sopenharmony_ci if (ret) { 12488c2ecf20Sopenharmony_ci dev_err(dev, "Failed to register algorithms with crypto %d\n", 12498c2ecf20Sopenharmony_ci ret); 12508c2ecf20Sopenharmony_ci goto queues_unconfig; 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, info); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci ret = sec_id_alloc(info); 12568c2ecf20Sopenharmony_ci if (ret) 12578c2ecf20Sopenharmony_ci goto algs_unregister; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci return 0; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_cialgs_unregister: 12628c2ecf20Sopenharmony_ci sec_algs_unregister(); 12638c2ecf20Sopenharmony_ciqueues_unconfig: 12648c2ecf20Sopenharmony_ci for (j = i - 1; j >= 0; j--) { 12658c2ecf20Sopenharmony_ci sec_queue_irq_uninit(&info->queues[j]); 12668c2ecf20Sopenharmony_ci sec_queue_unconfig(info, &info->queues[j]); 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci sec_base_exit(info); 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci return ret; 12718c2ecf20Sopenharmony_ci} 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_cistatic int sec_remove(struct platform_device *pdev) 12748c2ecf20Sopenharmony_ci{ 12758c2ecf20Sopenharmony_ci struct sec_dev_info *info = platform_get_drvdata(pdev); 12768c2ecf20Sopenharmony_ci int i; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci /* Unexpose as soon as possible, reuse during remove is fine */ 12798c2ecf20Sopenharmony_ci sec_id_free(info); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci sec_algs_unregister(); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci for (i = 0; i < SEC_Q_NUM; i++) { 12848c2ecf20Sopenharmony_ci sec_queue_irq_uninit(&info->queues[i]); 12858c2ecf20Sopenharmony_ci sec_queue_unconfig(info, &info->queues[i]); 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci sec_base_exit(info); 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci return 0; 12918c2ecf20Sopenharmony_ci} 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_cistatic const __maybe_unused struct of_device_id sec_match[] = { 12948c2ecf20Sopenharmony_ci { .compatible = "hisilicon,hip06-sec" }, 12958c2ecf20Sopenharmony_ci { .compatible = "hisilicon,hip07-sec" }, 12968c2ecf20Sopenharmony_ci {} 12978c2ecf20Sopenharmony_ci}; 12988c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, sec_match); 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_cistatic const __maybe_unused struct acpi_device_id sec_acpi_match[] = { 13018c2ecf20Sopenharmony_ci { "HISI02C1", 0 }, 13028c2ecf20Sopenharmony_ci { } 13038c2ecf20Sopenharmony_ci}; 13048c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, sec_acpi_match); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_cistatic struct platform_driver sec_driver = { 13078c2ecf20Sopenharmony_ci .probe = sec_probe, 13088c2ecf20Sopenharmony_ci .remove = sec_remove, 13098c2ecf20Sopenharmony_ci .driver = { 13108c2ecf20Sopenharmony_ci .name = "hisi_sec_platform_driver", 13118c2ecf20Sopenharmony_ci .of_match_table = sec_match, 13128c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(sec_acpi_match), 13138c2ecf20Sopenharmony_ci }, 13148c2ecf20Sopenharmony_ci}; 13158c2ecf20Sopenharmony_cimodule_platform_driver(sec_driver); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 13188c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Hisilicon Security Accelerators"); 13198c2ecf20Sopenharmony_ciMODULE_AUTHOR("Zaibo Xu <xuzaibo@huawei.com"); 13208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jonathan Cameron <jonathan.cameron@huawei.com>"); 1321