/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2021. All rights reserved. * Description:KS driver in register level. * Author: Hisilicon * Create: 2019/06/22 */ #include "hal_keyslot.h" #include "osal_ext.h" #include "drv_keyslot_define.h" #include "drv_keyslot_func.h" #include "hal_keyslot_reg.h" static td_void _ks_write_reg(const td_u32 addr, const td_u32 val) { struct ks_mgmt *mgmt = priv_get_ks_mgmt(); reg_write((mgmt->io_base + addr), val); ext_info_ks("ks w 0x%08x 0x%08x\n", mgmt->reg.reg + addr, val); return; } td_u32 _ks_read_reg(const td_u32 addr) { td_u32 val = 0; struct ks_mgmt *mgmt = priv_get_ks_mgmt(); reg_read((mgmt->io_base + addr), val); ext_info_ks("ks r 0x%08x 0x%08x\n", mgmt->reg.reg + addr, val); return val; } static td_u32 _ks_get_flush_status(td_void) { #ifdef CONFIG_SOCT_TEE_SUPPORT return _ks_read_reg(KC_REE_FLUSH_BUSY); #else return _ks_read_reg(KC_TEE_FLUSH_BUSY); #endif } static td_bool _ks_is_busy(td_void) { /* bit 0 is 1 means there is a key slot flushed by the current cpu */ return ((_ks_get_flush_status() & 0x1) != 0x0) ? TD_TRUE : TD_FALSE; } static td_bool _ks_flush_failed(td_void) { /* bit 1 is 1 means current cpu flush the target key slot due to time out */ return ((_ks_get_flush_status() & 0x2) != 0x0) ? TD_TRUE : TD_FALSE; } #define LOOP_MAX 1000 #define DELAY_US 1 static td_s32 _ks_flush_wait(td_void) { td_u32 time_out = LOOP_MAX; while (time_out--) { if (_ks_is_busy() == TD_FALSE) { break; } osal_udelay(DELAY_US); } if (time_out == 0) { return SOC_ERR_KS_STAT_TIME_OUT; } if (_ks_flush_failed()) { return SOC_ERR_KS_FLUSH_TIME_OUT; } return TD_SUCCESS; } static td_bool _ks_is_tscipher(const ext_keyslot_type slot_ind) { if (slot_ind == EXT_KEYSLOT_TYPE_TSCIPHER) { return TD_TRUE; } else { return TD_FALSE; } } ks_slot_stat hal_ks_status(const ext_keyslot_type slot_ind, const td_u32 slot_num) { kc_rd_lock_status stat; kc_rd_slot_num slot; slot.u32 = _ks_read_reg(KC_RD_SLOT_NUM); slot.bits.tscipher_slot_ind = _ks_is_tscipher(slot_ind); slot.bits.slot_num_cfg = slot_num; _ks_write_reg(KC_RD_SLOT_NUM, slot.u32); stat.u32 = _ks_read_reg(KC_RD_LOCK_STATUS); return (ks_slot_stat)stat.bits.rd_lock_status; } td_s32 hal_ks_lock(const ext_keyslot_type slot_ind, const td_u32 slot_num) { ks_slot_stat state; #ifdef CONFIG_SOCT_TEE_SUPPORT kc_ree_lock_cmd ree_reg; if (_ks_is_busy()) { return SOC_ERR_KS_BUSY; } ree_reg.u32 = _ks_read_reg(KC_REE_LOCK_CMD); ree_reg.bits.ree_lock_cmd = 1; ree_reg.bits.ree_tscipher_ind = _ks_is_tscipher(slot_ind); ree_reg.bits.ree_key_slot_num = slot_num; _ks_write_reg(KC_REE_LOCK_CMD, ree_reg.u32); state = hal_ks_status(slot_ind, slot_num); if (state != KS_STAT_REE_LOCK) { return SOC_ERR_KS_LOCKED_CPUX + state; } #else kc_tee_lock_cmd tee_reg; if (_ks_is_busy()) { return SOC_ERR_KS_BUSY; } tee_reg.u32 = _ks_read_reg(KC_TEE_LOCK_CMD); tee_reg.bits.tee_lock_cmd = 1; tee_reg.bits.tpp_key_enable = 1; tee_reg.bits.tee_tscipher_ind = _ks_is_tscipher(slot_ind); tee_reg.bits.tee_key_slot_num = slot_num; _ks_write_reg(KC_TEE_LOCK_CMD, tee_reg.u32); state = hal_ks_status(slot_ind, slot_num); if (state != KS_STAT_TEE_LOCK) { return SOC_ERR_KS_LOCKED_CPUX + state; } #endif return TD_SUCCESS; } td_s32 hal_ks_unlock(const ext_keyslot_type slot_ind, const td_u32 slot_num) { #ifdef CONFIG_SOCT_TEE_SUPPORT kc_ree_lock_cmd ree_reg; if (_ks_is_busy()) { return SOC_ERR_KS_BUSY; } ree_reg.u32 = _ks_read_reg(KC_REE_LOCK_CMD); ree_reg.bits.ree_lock_cmd = 0; ree_reg.bits.ree_tscipher_ind = _ks_is_tscipher(slot_ind); ree_reg.bits.ree_key_slot_num = slot_num; _ks_write_reg(KC_REE_LOCK_CMD, ree_reg.u32); #else kc_tee_lock_cmd tee_reg; if (_ks_is_busy()) { return SOC_ERR_KS_BUSY; } tee_reg.u32 = _ks_read_reg(KC_TEE_LOCK_CMD); tee_reg.bits.tee_lock_cmd = 0; tee_reg.bits.tee_tscipher_ind = _ks_is_tscipher(slot_ind); tee_reg.bits.tee_key_slot_num = slot_num; _ks_write_reg(KC_TEE_LOCK_CMD, tee_reg.u32); #endif return _ks_flush_wait(); }