mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
ufs: ice: add variant ops for ICE
Add QTI implementation for variant ops required for inline encryption with wrapped key support. These include UFS crypto ops and KSM ops. Change-Id: Ica930a8a806a78d4c2d074639cbed355b895a459 Signed-off-by: Gaurav Kashyap <gaurkash@codeaurora.org>
This commit is contained in:
parent
3a82802e7b
commit
54905869ef
12 changed files with 1194 additions and 0 deletions
|
|
@ -177,3 +177,11 @@ config SCSI_UFS_CRYPTO
|
|||
Enabling this makes it possible for the kernel to use the crypto
|
||||
capabilities of the UFS device (if present) to perform crypto
|
||||
operations on data being transferred to/from the device.
|
||||
|
||||
config SCSI_UFS_CRYPTO_QTI
|
||||
tristate "Vendor specific UFS Crypto Engine Support"
|
||||
depends on SCSI_UFS_CRYPTO
|
||||
help
|
||||
Enable Vendor Crypto Engine Support in UFS
|
||||
Enabling this allows kernel to use UFS crypto operations defined
|
||||
and implemented by QTI.
|
||||
|
|
|
|||
|
|
@ -16,3 +16,5 @@ ufshcd-qti-core-y += ufshcd-qti.o ufs-sysfs.o
|
|||
ufshcd-qti-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
|
||||
ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO) += ufshcd-crypto.o
|
||||
ufshcd-qti-core-$(CONFIG_SCSI_UFS_CRYPTO) += ufshcd-crypto.o
|
||||
ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO_QTI) += ufshcd-crypto-qti.o
|
||||
ufshcd-qti-core-$(CONFIG_SCSI_UFS_CRYPTO_QTI) += ufshcd-crypto-qti.o
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include "ufs-qcom.h"
|
||||
#include "ufshci.h"
|
||||
#include "ufs_quirks.h"
|
||||
#include "ufshcd-crypto-qti.h"
|
||||
|
||||
#define UFS_QCOM_DEFAULT_DBG_PRINT_EN \
|
||||
(UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
|
||||
|
||||
|
|
@ -2149,6 +2151,12 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
|||
goto out_variant_clear;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the vendor specific ops needed for ICE.
|
||||
* Default implementation if the ops are not set.
|
||||
*/
|
||||
ufshcd_crypto_qti_set_vops(hba);
|
||||
|
||||
err = ufs_qcom_bus_register(host);
|
||||
if (err)
|
||||
goto out_variant_clear;
|
||||
|
|
|
|||
297
drivers/scsi/ufs/ufshcd-crypto-qti.c
Normal file
297
drivers/scsi/ufs/ufshcd-crypto-qti.c
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* UFS Crypto ops QTI implementation.
|
||||
*
|
||||
* Copyright (c) 2020, Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <crypto/algapi.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/crypto-qti-common.h>
|
||||
|
||||
#include "ufshcd-crypto-qti.h"
|
||||
|
||||
#define MINIMUM_DUN_SIZE 512
|
||||
#define MAXIMUM_DUN_SIZE 65536
|
||||
|
||||
#define NUM_KEYSLOTS(hba) (hba->crypto_capabilities.config_count + 1)
|
||||
|
||||
static struct ufs_hba_crypto_variant_ops ufshcd_crypto_qti_variant_ops = {
|
||||
.hba_init_crypto = ufshcd_crypto_qti_init_crypto,
|
||||
.enable = ufshcd_crypto_qti_enable,
|
||||
.disable = ufshcd_crypto_qti_disable,
|
||||
.resume = ufshcd_crypto_qti_resume,
|
||||
.debug = ufshcd_crypto_qti_debug,
|
||||
};
|
||||
|
||||
static uint8_t get_data_unit_size_mask(unsigned int data_unit_size)
|
||||
{
|
||||
if (data_unit_size < MINIMUM_DUN_SIZE ||
|
||||
data_unit_size > MAXIMUM_DUN_SIZE ||
|
||||
!is_power_of_2(data_unit_size))
|
||||
return 0;
|
||||
|
||||
return data_unit_size / MINIMUM_DUN_SIZE;
|
||||
}
|
||||
|
||||
static bool ice_cap_idx_valid(struct ufs_hba *hba,
|
||||
unsigned int cap_idx)
|
||||
{
|
||||
return cap_idx < hba->crypto_capabilities.num_crypto_cap;
|
||||
}
|
||||
|
||||
void ufshcd_crypto_qti_enable(struct ufs_hba *hba)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!ufshcd_hba_is_crypto_supported(hba))
|
||||
return;
|
||||
|
||||
err = crypto_qti_enable(hba->crypto_vops->priv);
|
||||
if (err) {
|
||||
pr_err("%s: Error enabling crypto, err %d\n",
|
||||
__func__, err);
|
||||
ufshcd_crypto_qti_disable(hba);
|
||||
}
|
||||
|
||||
ufshcd_crypto_enable_spec(hba);
|
||||
|
||||
}
|
||||
|
||||
void ufshcd_crypto_qti_disable(struct ufs_hba *hba)
|
||||
{
|
||||
ufshcd_crypto_disable_spec(hba);
|
||||
crypto_qti_disable(hba->crypto_vops->priv);
|
||||
}
|
||||
|
||||
|
||||
static int ufshcd_crypto_qti_keyslot_program(struct keyslot_manager *ksm,
|
||||
const struct blk_crypto_key *key,
|
||||
unsigned int slot)
|
||||
{
|
||||
struct ufs_hba *hba = keyslot_manager_private(ksm);
|
||||
int err = 0;
|
||||
u8 data_unit_mask;
|
||||
int crypto_alg_id;
|
||||
|
||||
crypto_alg_id = ufshcd_crypto_cap_find(hba, key->crypto_mode,
|
||||
key->data_unit_size);
|
||||
|
||||
if (!ufshcd_is_crypto_enabled(hba) ||
|
||||
!ufshcd_keyslot_valid(hba, slot) ||
|
||||
!ice_cap_idx_valid(hba, crypto_alg_id))
|
||||
return -EINVAL;
|
||||
|
||||
data_unit_mask = get_data_unit_size_mask(key->data_unit_size);
|
||||
|
||||
if (!(data_unit_mask &
|
||||
hba->crypto_cap_array[crypto_alg_id].sdus_mask))
|
||||
return -EINVAL;
|
||||
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
err = ufshcd_hold(hba, false);
|
||||
if (err) {
|
||||
pr_err("%s: failed to enable clocks, err %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = crypto_qti_keyslot_program(hba->crypto_vops->priv, key, slot,
|
||||
data_unit_mask, crypto_alg_id);
|
||||
if (err) {
|
||||
pr_err("%s: failed with error %d\n", __func__, err);
|
||||
ufshcd_release(hba);
|
||||
pm_runtime_put_sync(hba->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
ufshcd_release(hba);
|
||||
pm_runtime_put_sync(hba->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ufshcd_crypto_qti_keyslot_evict(struct keyslot_manager *ksm,
|
||||
const struct blk_crypto_key *key,
|
||||
unsigned int slot)
|
||||
{
|
||||
int err = 0;
|
||||
struct ufs_hba *hba = keyslot_manager_private(ksm);
|
||||
|
||||
if (!ufshcd_is_crypto_enabled(hba) ||
|
||||
!ufshcd_keyslot_valid(hba, slot))
|
||||
return -EINVAL;
|
||||
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
err = ufshcd_hold(hba, false);
|
||||
if (err) {
|
||||
pr_err("%s: failed to enable clocks, err %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = crypto_qti_keyslot_evict(hba->crypto_vops->priv, slot);
|
||||
if (err) {
|
||||
pr_err("%s: failed with error %d\n",
|
||||
__func__, err);
|
||||
ufshcd_release(hba);
|
||||
pm_runtime_put_sync(hba->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
ufshcd_release(hba);
|
||||
pm_runtime_put_sync(hba->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufshcd_crypto_qti_derive_raw_secret(struct keyslot_manager *ksm,
|
||||
const u8 *wrapped_key,
|
||||
unsigned int wrapped_key_size,
|
||||
u8 *secret,
|
||||
unsigned int secret_size)
|
||||
{
|
||||
return crypto_qti_derive_raw_secret(wrapped_key, wrapped_key_size,
|
||||
secret, secret_size);
|
||||
}
|
||||
|
||||
static const struct keyslot_mgmt_ll_ops ufshcd_crypto_qti_ksm_ops = {
|
||||
.keyslot_program = ufshcd_crypto_qti_keyslot_program,
|
||||
.keyslot_evict = ufshcd_crypto_qti_keyslot_evict,
|
||||
.derive_raw_secret = ufshcd_crypto_qti_derive_raw_secret,
|
||||
};
|
||||
|
||||
static enum blk_crypto_mode_num ufshcd_blk_crypto_qti_mode_num_for_alg_dusize(
|
||||
enum ufs_crypto_alg ufs_crypto_alg,
|
||||
enum ufs_crypto_key_size key_size)
|
||||
{
|
||||
/*
|
||||
* This is currently the only mode that UFS and blk-crypto both support.
|
||||
*/
|
||||
if (ufs_crypto_alg == UFS_CRYPTO_ALG_AES_XTS &&
|
||||
key_size == UFS_CRYPTO_KEY_SIZE_256)
|
||||
return BLK_ENCRYPTION_MODE_AES_256_XTS;
|
||||
|
||||
return BLK_ENCRYPTION_MODE_INVALID;
|
||||
}
|
||||
|
||||
static int ufshcd_hba_init_crypto_qti_spec(struct ufs_hba *hba,
|
||||
const struct keyslot_mgmt_ll_ops *ksm_ops)
|
||||
{
|
||||
int cap_idx = 0;
|
||||
int err = 0;
|
||||
unsigned int crypto_modes_supported[BLK_ENCRYPTION_MODE_MAX];
|
||||
enum blk_crypto_mode_num blk_mode_num;
|
||||
|
||||
/* Default to disabling crypto */
|
||||
hba->caps &= ~UFSHCD_CAP_CRYPTO;
|
||||
|
||||
if (!(hba->capabilities & MASK_CRYPTO_SUPPORT)) {
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Crypto Capabilities should never be 0, because the
|
||||
* config_array_ptr > 04h. So we use a 0 value to indicate that
|
||||
* crypto init failed, and can't be enabled.
|
||||
*/
|
||||
hba->crypto_capabilities.reg_val =
|
||||
cpu_to_le32(ufshcd_readl(hba, REG_UFS_CCAP));
|
||||
hba->crypto_cfg_register =
|
||||
(u32)hba->crypto_capabilities.config_array_ptr * 0x100;
|
||||
hba->crypto_cap_array =
|
||||
devm_kcalloc(hba->dev,
|
||||
hba->crypto_capabilities.num_crypto_cap,
|
||||
sizeof(hba->crypto_cap_array[0]),
|
||||
GFP_KERNEL);
|
||||
if (!hba->crypto_cap_array) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(crypto_modes_supported, 0, sizeof(crypto_modes_supported));
|
||||
/*
|
||||
* Store all the capabilities now so that we don't need to repeatedly
|
||||
* access the device each time we want to know its capabilities
|
||||
*/
|
||||
for (cap_idx = 0; cap_idx < hba->crypto_capabilities.num_crypto_cap;
|
||||
cap_idx++) {
|
||||
hba->crypto_cap_array[cap_idx].reg_val =
|
||||
cpu_to_le32(ufshcd_readl(hba,
|
||||
REG_UFS_CRYPTOCAP +
|
||||
cap_idx * sizeof(__le32)));
|
||||
blk_mode_num = ufshcd_blk_crypto_qti_mode_num_for_alg_dusize(
|
||||
hba->crypto_cap_array[cap_idx].algorithm_id,
|
||||
hba->crypto_cap_array[cap_idx].key_size);
|
||||
if (blk_mode_num == BLK_ENCRYPTION_MODE_INVALID)
|
||||
continue;
|
||||
crypto_modes_supported[blk_mode_num] |=
|
||||
hba->crypto_cap_array[cap_idx].sdus_mask * 512;
|
||||
}
|
||||
|
||||
hba->ksm = keyslot_manager_create(ufshcd_num_keyslots(hba), ksm_ops,
|
||||
crypto_modes_supported, hba);
|
||||
|
||||
if (!hba->ksm) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
pr_debug("%s: keyslot manager created\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
/* Indicate that init failed by setting crypto_capabilities to 0 */
|
||||
hba->crypto_capabilities.reg_val = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int ufshcd_crypto_qti_init_crypto(struct ufs_hba *hba,
|
||||
const struct keyslot_mgmt_ll_ops *ksm_ops)
|
||||
{
|
||||
int err = 0;
|
||||
struct platform_device *pdev = to_platform_device(hba->dev);
|
||||
void __iomem *mmio_base;
|
||||
struct resource *mem_res;
|
||||
|
||||
mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"ufs_ice");
|
||||
mmio_base = devm_ioremap_resource(hba->dev, mem_res);
|
||||
if (IS_ERR(mmio_base)) {
|
||||
pr_err("%s: Unable to get ufs_crypto mmio base\n", __func__);
|
||||
return PTR_ERR(mmio_base);
|
||||
}
|
||||
|
||||
err = ufshcd_hba_init_crypto_qti_spec(hba, &ufshcd_crypto_qti_ksm_ops);
|
||||
if (err) {
|
||||
pr_err("%s: Error initiating crypto capabilities, err %d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = crypto_qti_init_crypto(hba->dev,
|
||||
mmio_base, (void **)&hba->crypto_vops->priv);
|
||||
if (err) {
|
||||
pr_err("%s: Error initiating crypto, err %d\n",
|
||||
__func__, err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int ufshcd_crypto_qti_debug(struct ufs_hba *hba)
|
||||
{
|
||||
return crypto_qti_debug(hba->crypto_vops->priv);
|
||||
}
|
||||
|
||||
void ufshcd_crypto_qti_set_vops(struct ufs_hba *hba)
|
||||
{
|
||||
return ufshcd_crypto_set_vops(hba, &ufshcd_crypto_qti_variant_ops);
|
||||
}
|
||||
|
||||
int ufshcd_crypto_qti_resume(struct ufs_hba *hba,
|
||||
enum ufs_pm_op pm_op)
|
||||
{
|
||||
return crypto_qti_resume(hba->crypto_vops->priv);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("UFS Crypto ops QTI implementation");
|
||||
43
drivers/scsi/ufs/ufshcd-crypto-qti.h
Normal file
43
drivers/scsi/ufs/ufshcd-crypto-qti.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UFSHCD_CRYPTO_QTI_H
|
||||
#define _UFSHCD_CRYPTO_QTI_H
|
||||
|
||||
#include "ufshcd.h"
|
||||
#include "ufshcd-crypto.h"
|
||||
|
||||
void ufshcd_crypto_qti_enable(struct ufs_hba *hba);
|
||||
|
||||
void ufshcd_crypto_qti_disable(struct ufs_hba *hba);
|
||||
|
||||
int ufshcd_crypto_qti_init_crypto(struct ufs_hba *hba,
|
||||
const struct keyslot_mgmt_ll_ops *ksm_ops);
|
||||
|
||||
void ufshcd_crypto_qti_setup_rq_keyslot_manager(struct ufs_hba *hba,
|
||||
struct request_queue *q);
|
||||
|
||||
void ufshcd_crypto_qti_destroy_rq_keyslot_manager(struct ufs_hba *hba,
|
||||
struct request_queue *q);
|
||||
|
||||
int ufshcd_crypto_qti_prepare_lrbp_crypto(struct ufs_hba *hba,
|
||||
struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp);
|
||||
|
||||
int ufshcd_crypto_qti_complete_lrbp_crypto(struct ufs_hba *hba,
|
||||
struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp);
|
||||
|
||||
int ufshcd_crypto_qti_debug(struct ufs_hba *hba);
|
||||
|
||||
int ufshcd_crypto_qti_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op);
|
||||
|
||||
int ufshcd_crypto_qti_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op);
|
||||
|
||||
#ifdef CONFIG_SCSI_UFS_CRYPTO_QTI
|
||||
void ufshcd_crypto_qti_set_vops(struct ufs_hba *hba);
|
||||
#else
|
||||
static inline void ufshcd_crypto_qti_set_vops(struct ufs_hba *hba)
|
||||
{}
|
||||
#endif /* CONFIG_SCSI_UFS_CRYPTO_QTI */
|
||||
#endif /* _UFSHCD_CRYPTO_QTI_H */
|
||||
|
|
@ -782,4 +782,22 @@ config QCOM_HYP_CORE_CTL
|
|||
An offline CPU is considered as a reserved CPU since this OS can't use
|
||||
it.
|
||||
|
||||
config QTI_CRYPTO_COMMON
|
||||
tristate "Enable common crypto functionality used for FBE"
|
||||
depends on SCSI_UFS_CRYPTO_QTI
|
||||
help
|
||||
Say 'Y' to enable the common crypto implementation to be used by
|
||||
different storage layers such as UFS and EMMC for file based hardware
|
||||
encryption. This library implements API to program and evict
|
||||
keys using Trustzone or Hardware Key Manager.
|
||||
|
||||
config QTI_CRYPTO_TZ
|
||||
tristate "Enable Trustzone to be used for FBE"
|
||||
depends on QTI_CRYPTO_COMMON
|
||||
help
|
||||
Say 'Y' to enable routing crypto requests to Trustzone while
|
||||
performing hardware based file encryption. This means keys are
|
||||
programmed and managed through SCM calls to TZ where ICE driver
|
||||
will configure keys.
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -74,3 +74,5 @@ obj-$(CONFIG_QCOM_EUD) += eud.o
|
|||
obj-$(CONFIG_QCOM_GUESTVM) += guestvm_loader.o
|
||||
obj-$(CONFIG_QCOM_HYP_CORE_CTL) += hyp_core_ctl.o
|
||||
obj-$(CONFIG_MSM_QBT_HANDLER) += qbt_handler.o
|
||||
obj-$(CONFIG_QTI_CRYPTO_COMMON) += crypto-qti-common.o
|
||||
obj-$(CONFIG_QTI_CRYPTO_TZ) += crypto-qti-tz.o
|
||||
|
|
|
|||
471
drivers/soc/qcom/crypto-qti-common.c
Normal file
471
drivers/soc/qcom/crypto-qti-common.c
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Common crypto library for storage encryption.
|
||||
*
|
||||
* Copyright (c) 2020, Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/crypto-qti-common.h>
|
||||
#include <linux/module.h>
|
||||
#include "crypto-qti-ice-regs.h"
|
||||
#include "crypto-qti-platform.h"
|
||||
|
||||
static int ice_check_fuse_setting(struct crypto_vops_qti_entry *ice_entry)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t major, minor;
|
||||
|
||||
major = (ice_entry->ice_hw_version & ICE_CORE_MAJOR_REV_MASK) >>
|
||||
ICE_CORE_MAJOR_REV;
|
||||
minor = (ice_entry->ice_hw_version & ICE_CORE_MINOR_REV_MASK) >>
|
||||
ICE_CORE_MINOR_REV;
|
||||
|
||||
//Check fuse setting is not supported on ICE 3.2 onwards
|
||||
if ((major == 0x03) && (minor >= 0x02))
|
||||
return 0;
|
||||
regval = ice_readl(ice_entry, ICE_REGS_FUSE_SETTING);
|
||||
regval &= (ICE_FUSE_SETTING_MASK |
|
||||
ICE_FORCE_HW_KEY0_SETTING_MASK |
|
||||
ICE_FORCE_HW_KEY1_SETTING_MASK);
|
||||
|
||||
if (regval) {
|
||||
pr_err("%s: error: ICE_ERROR_HW_DISABLE_FUSE_BLOWN\n",
|
||||
__func__);
|
||||
return -EPERM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ice_check_version(struct crypto_vops_qti_entry *ice_entry)
|
||||
{
|
||||
uint32_t version, major, minor, step;
|
||||
|
||||
version = ice_readl(ice_entry, ICE_REGS_VERSION);
|
||||
major = (version & ICE_CORE_MAJOR_REV_MASK) >> ICE_CORE_MAJOR_REV;
|
||||
minor = (version & ICE_CORE_MINOR_REV_MASK) >> ICE_CORE_MINOR_REV;
|
||||
step = (version & ICE_CORE_STEP_REV_MASK) >> ICE_CORE_STEP_REV;
|
||||
|
||||
if (major < ICE_CORE_CURRENT_MAJOR_VERSION) {
|
||||
pr_err("%s: Unknown ICE device at %lu, rev %d.%d.%d\n",
|
||||
__func__, (unsigned long)ice_entry->icemmio_base,
|
||||
major, minor, step);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ice_entry->ice_hw_version = version;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypto_qti_init_crypto(struct device *dev, void __iomem *mmio_base,
|
||||
void **priv_data)
|
||||
{
|
||||
int err = 0;
|
||||
struct crypto_vops_qti_entry *ice_entry;
|
||||
|
||||
ice_entry = devm_kzalloc(dev,
|
||||
sizeof(struct crypto_vops_qti_entry),
|
||||
GFP_KERNEL);
|
||||
if (!ice_entry)
|
||||
return -ENOMEM;
|
||||
|
||||
ice_entry->icemmio_base = mmio_base;
|
||||
ice_entry->flags = 0;
|
||||
|
||||
err = ice_check_version(ice_entry);
|
||||
if (err) {
|
||||
pr_err("%s: check version failed, err %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ice_check_fuse_setting(ice_entry);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*priv_data = (void *)ice_entry;
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_init_crypto);
|
||||
|
||||
static void ice_low_power_and_optimization_enable(
|
||||
struct crypto_vops_qti_entry *ice_entry)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
regval = ice_readl(ice_entry, ICE_REGS_ADVANCED_CONTROL);
|
||||
/* Enable low power mode sequence
|
||||
* [0]-0,[1]-0,[2]-0,[3]-7,[4]-0,[5]-0,[6]-0,[7]-0,
|
||||
* Enable CONFIG_CLK_GATING, STREAM2_CLK_GATING and STREAM1_CLK_GATING
|
||||
*/
|
||||
regval |= 0x7000;
|
||||
/* Optimization enable sequence
|
||||
*/
|
||||
regval |= 0xD807100;
|
||||
ice_writel(ice_entry, regval, ICE_REGS_ADVANCED_CONTROL);
|
||||
/*
|
||||
* Memory barrier - to ensure write completion before next transaction
|
||||
*/
|
||||
wmb();
|
||||
}
|
||||
|
||||
static int ice_wait_bist_status(struct crypto_vops_qti_entry *ice_entry)
|
||||
{
|
||||
int count;
|
||||
uint32_t regval;
|
||||
|
||||
for (count = 0; count < QTI_ICE_MAX_BIST_CHECK_COUNT; count++) {
|
||||
regval = ice_readl(ice_entry, ICE_REGS_BIST_STATUS);
|
||||
if (!(regval & ICE_BIST_STATUS_MASK))
|
||||
break;
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
if (regval) {
|
||||
pr_err("%s: wait bist status failed, reg %d\n",
|
||||
__func__, regval);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ice_enable_intr(struct crypto_vops_qti_entry *ice_entry)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
regval = ice_readl(ice_entry, ICE_REGS_NON_SEC_IRQ_MASK);
|
||||
regval &= ~ICE_REGS_NON_SEC_IRQ_MASK;
|
||||
ice_writel(ice_entry, regval, ICE_REGS_NON_SEC_IRQ_MASK);
|
||||
/*
|
||||
* Memory barrier - to ensure write completion before next transaction
|
||||
*/
|
||||
wmb();
|
||||
}
|
||||
|
||||
static void ice_disable_intr(struct crypto_vops_qti_entry *ice_entry)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
regval = ice_readl(ice_entry, ICE_REGS_NON_SEC_IRQ_MASK);
|
||||
regval |= ICE_REGS_NON_SEC_IRQ_MASK;
|
||||
ice_writel(ice_entry, regval, ICE_REGS_NON_SEC_IRQ_MASK);
|
||||
/*
|
||||
* Memory barrier - to ensure write completion before next transaction
|
||||
*/
|
||||
wmb();
|
||||
}
|
||||
|
||||
int crypto_qti_enable(void *priv_data)
|
||||
{
|
||||
int err = 0;
|
||||
struct crypto_vops_qti_entry *ice_entry;
|
||||
|
||||
ice_entry = (struct crypto_vops_qti_entry *) priv_data;
|
||||
if (!ice_entry) {
|
||||
pr_err("%s: vops ice data is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ice_low_power_and_optimization_enable(ice_entry);
|
||||
err = ice_wait_bist_status(ice_entry);
|
||||
if (err)
|
||||
return err;
|
||||
ice_enable_intr(ice_entry);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_enable);
|
||||
|
||||
void crypto_qti_disable(void *priv_data)
|
||||
{
|
||||
struct crypto_vops_qti_entry *ice_entry;
|
||||
|
||||
ice_entry = (struct crypto_vops_qti_entry *) priv_data;
|
||||
if (!ice_entry) {
|
||||
pr_err("%s: vops ice data is invalid\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
crypto_qti_disable_platform(ice_entry);
|
||||
ice_disable_intr(ice_entry);
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_disable);
|
||||
|
||||
int crypto_qti_resume(void *priv_data)
|
||||
{
|
||||
int err = 0;
|
||||
struct crypto_vops_qti_entry *ice_entry;
|
||||
|
||||
ice_entry = (struct crypto_vops_qti_entry *) priv_data;
|
||||
if (!ice_entry) {
|
||||
pr_err("%s: vops ice data is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = ice_wait_bist_status(ice_entry);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_resume);
|
||||
|
||||
static void ice_dump_test_bus(struct crypto_vops_qti_entry *ice_entry)
|
||||
{
|
||||
uint32_t regval = 0x1;
|
||||
uint32_t val;
|
||||
uint8_t bus_selector;
|
||||
uint8_t stream_selector;
|
||||
|
||||
pr_err("ICE TEST BUS DUMP:\n");
|
||||
|
||||
for (bus_selector = 0; bus_selector <= 0xF; bus_selector++) {
|
||||
regval = 0x1; /* enable test bus */
|
||||
regval |= bus_selector << 28;
|
||||
if (bus_selector == 0xD)
|
||||
continue;
|
||||
ice_writel(ice_entry, regval, ICE_REGS_TEST_BUS_CONTROL);
|
||||
/*
|
||||
* make sure test bus selector is written before reading
|
||||
* the test bus register
|
||||
*/
|
||||
wmb();
|
||||
val = ice_readl(ice_entry, ICE_REGS_TEST_BUS_REG);
|
||||
pr_err("ICE_TEST_BUS_CONTROL: 0x%08x | ICE_TEST_BUS_REG: 0x%08x\n",
|
||||
regval, val);
|
||||
}
|
||||
|
||||
pr_err("ICE TEST BUS DUMP (ICE_STREAM1_DATAPATH_TEST_BUS):\n");
|
||||
for (stream_selector = 0; stream_selector <= 0xF; stream_selector++) {
|
||||
regval = 0xD0000001; /* enable stream test bus */
|
||||
regval |= stream_selector << 16;
|
||||
ice_writel(ice_entry, regval, ICE_REGS_TEST_BUS_CONTROL);
|
||||
/*
|
||||
* make sure test bus selector is written before reading
|
||||
* the test bus register
|
||||
*/
|
||||
wmb();
|
||||
val = ice_readl(ice_entry, ICE_REGS_TEST_BUS_REG);
|
||||
pr_err("ICE_TEST_BUS_CONTROL: 0x%08x | ICE_TEST_BUS_REG: 0x%08x\n",
|
||||
regval, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crypto_qti_debug(void *priv_data)
|
||||
{
|
||||
struct crypto_vops_qti_entry *ice_entry;
|
||||
|
||||
ice_entry = (struct crypto_vops_qti_entry *) priv_data;
|
||||
if (!ice_entry) {
|
||||
pr_err("%s: vops ice data is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_err("%s: ICE Control: 0x%08x | ICE Reset: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_CONTROL),
|
||||
ice_readl(ice_entry, ICE_REGS_RESET));
|
||||
|
||||
pr_err("%s: ICE Version: 0x%08x | ICE FUSE: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_VERSION),
|
||||
ice_readl(ice_entry, ICE_REGS_FUSE_SETTING));
|
||||
|
||||
pr_err("%s: ICE Param1: 0x%08x | ICE Param2: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_PARAMETERS_1),
|
||||
ice_readl(ice_entry, ICE_REGS_PARAMETERS_2));
|
||||
|
||||
pr_err("%s: ICE Param3: 0x%08x | ICE Param4: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_PARAMETERS_3),
|
||||
ice_readl(ice_entry, ICE_REGS_PARAMETERS_4));
|
||||
|
||||
pr_err("%s: ICE Param5: 0x%08x | ICE IRQ STTS: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_PARAMETERS_5),
|
||||
ice_readl(ice_entry, ICE_REGS_NON_SEC_IRQ_STTS));
|
||||
|
||||
pr_err("%s: ICE IRQ MASK: 0x%08x | ICE IRQ CLR: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_NON_SEC_IRQ_MASK),
|
||||
ice_readl(ice_entry, ICE_REGS_NON_SEC_IRQ_CLR));
|
||||
|
||||
pr_err("%s: ICE INVALID CCFG ERR STTS: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_INVALID_CCFG_ERR_STTS));
|
||||
|
||||
pr_err("%s: ICE BIST Sts: 0x%08x | ICE Bypass Sts: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_BIST_STATUS),
|
||||
ice_readl(ice_entry, ICE_REGS_BYPASS_STATUS));
|
||||
|
||||
pr_err("%s: ICE ADV CTRL: 0x%08x | ICE ENDIAN SWAP: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_ADVANCED_CONTROL),
|
||||
ice_readl(ice_entry, ICE_REGS_ENDIAN_SWAP));
|
||||
|
||||
pr_err("%s: ICE_STM1_ERR_SYND1: 0x%08x | ICE_STM1_ERR_SYND2: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_ERROR_SYNDROME1),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_ERROR_SYNDROME2));
|
||||
|
||||
pr_err("%s: ICE_STM2_ERR_SYND1: 0x%08x | ICE_STM2_ERR_SYND2: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_ERROR_SYNDROME1),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_ERROR_SYNDROME2));
|
||||
|
||||
pr_err("%s: ICE_STM1_COUNTER1: 0x%08x | ICE_STM1_COUNTER2: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS1),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS2));
|
||||
|
||||
pr_err("%s: ICE_STM1_COUNTER3: 0x%08x | ICE_STM1_COUNTER4: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS3),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS4));
|
||||
|
||||
pr_err("%s: ICE_STM2_COUNTER1: 0x%08x | ICE_STM2_COUNTER2: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS1),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS2));
|
||||
|
||||
pr_err("%s: ICE_STM2_COUNTER3: 0x%08x | ICE_STM2_COUNTER4: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS3),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS4));
|
||||
|
||||
pr_err("%s: ICE_STM1_CTR5_MSB: 0x%08x | ICE_STM1_CTR5_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS5_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS5_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM1_CTR6_MSB: 0x%08x | ICE_STM1_CTR6_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS6_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS6_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM1_CTR7_MSB: 0x%08x | ICE_STM1_CTR7_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS7_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS7_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM1_CTR8_MSB: 0x%08x | ICE_STM1_CTR8_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS8_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS8_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM1_CTR9_MSB: 0x%08x | ICE_STM1_CTR9_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS9_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM1_COUNTERS9_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM2_CTR5_MSB: 0x%08x | ICE_STM2_CTR5_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS5_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS5_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM2_CTR6_MSB: 0x%08x | ICE_STM2_CTR6_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS6_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS6_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM2_CTR7_MSB: 0x%08x | ICE_STM2_CTR7_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS7_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS7_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM2_CTR8_MSB: 0x%08x | ICE_STM2_CTR8_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS8_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS8_LSB));
|
||||
|
||||
pr_err("%s: ICE_STM2_CTR9_MSB: 0x%08x | ICE_STM2_CTR9_LSB: 0x%08x\n",
|
||||
ice_entry->ice_dev_type,
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS9_MSB),
|
||||
ice_readl(ice_entry, ICE_REGS_STREAM2_COUNTERS9_LSB));
|
||||
|
||||
ice_dump_test_bus(ice_entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_debug);
|
||||
|
||||
int crypto_qti_keyslot_program(void *priv_data,
|
||||
const struct blk_crypto_key *key,
|
||||
unsigned int slot,
|
||||
u8 data_unit_mask, int capid)
|
||||
{
|
||||
int err = 0;
|
||||
struct crypto_vops_qti_entry *ice_entry;
|
||||
|
||||
ice_entry = (struct crypto_vops_qti_entry *) priv_data;
|
||||
if (!ice_entry) {
|
||||
pr_err("%s: vops ice data is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = crypto_qti_program_key(ice_entry, key, slot,
|
||||
data_unit_mask, capid);
|
||||
if (err) {
|
||||
pr_err("%s: program key failed with error %d\n", __func__, err);
|
||||
err = crypto_qti_invalidate_key(ice_entry, slot);
|
||||
if (err) {
|
||||
pr_err("%s: invalidate key failed with error %d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_keyslot_program);
|
||||
|
||||
int crypto_qti_keyslot_evict(void *priv_data, unsigned int slot)
|
||||
{
|
||||
int err = 0;
|
||||
struct crypto_vops_qti_entry *ice_entry;
|
||||
|
||||
ice_entry = (struct crypto_vops_qti_entry *) priv_data;
|
||||
if (!ice_entry) {
|
||||
pr_err("%s: vops ice data is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = crypto_qti_invalidate_key(ice_entry, slot);
|
||||
if (err) {
|
||||
pr_err("%s: invalidate key failed with error %d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_keyslot_evict);
|
||||
|
||||
int crypto_qti_derive_raw_secret(const u8 *wrapped_key,
|
||||
unsigned int wrapped_key_size, u8 *secret,
|
||||
unsigned int secret_size)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (wrapped_key_size <= RAW_SECRET_SIZE) {
|
||||
pr_err("%s: Invalid wrapped_key_size: %u\n",
|
||||
__func__, wrapped_key_size);
|
||||
err = -EINVAL;
|
||||
return err;
|
||||
}
|
||||
if (secret_size != RAW_SECRET_SIZE) {
|
||||
pr_err("%s: Invalid secret size: %u\n", __func__, secret_size);
|
||||
err = -EINVAL;
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(secret, wrapped_key, secret_size);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_derive_raw_secret);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Common crypto library for storage encryption");
|
||||
156
drivers/soc/qcom/crypto-qti-ice-regs.h
Normal file
156
drivers/soc/qcom/crypto-qti-ice-regs.h
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_INLINE_CRYPTO_ENGINE_REGS_H_
|
||||
#define _CRYPTO_INLINE_CRYPTO_ENGINE_REGS_H_
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
/* Register bits for ICE version */
|
||||
#define ICE_CORE_CURRENT_MAJOR_VERSION 0x03
|
||||
|
||||
#define ICE_CORE_STEP_REV_MASK 0xFFFF
|
||||
#define ICE_CORE_STEP_REV 0 /* bit 15-0 */
|
||||
#define ICE_CORE_MAJOR_REV_MASK 0xFF000000
|
||||
#define ICE_CORE_MAJOR_REV 24 /* bit 31-24 */
|
||||
#define ICE_CORE_MINOR_REV_MASK 0xFF0000
|
||||
#define ICE_CORE_MINOR_REV 16 /* bit 23-16 */
|
||||
|
||||
#define ICE_BIST_STATUS_MASK (0xF0000000) /* bits 28-31 */
|
||||
|
||||
#define ICE_FUSE_SETTING_MASK 0x1
|
||||
#define ICE_FORCE_HW_KEY0_SETTING_MASK 0x2
|
||||
#define ICE_FORCE_HW_KEY1_SETTING_MASK 0x4
|
||||
|
||||
/* QTI ICE Registers from SWI */
|
||||
#define ICE_REGS_CONTROL 0x0000
|
||||
#define ICE_REGS_RESET 0x0004
|
||||
#define ICE_REGS_VERSION 0x0008
|
||||
#define ICE_REGS_FUSE_SETTING 0x0010
|
||||
#define ICE_REGS_PARAMETERS_1 0x0014
|
||||
#define ICE_REGS_PARAMETERS_2 0x0018
|
||||
#define ICE_REGS_PARAMETERS_3 0x001C
|
||||
#define ICE_REGS_PARAMETERS_4 0x0020
|
||||
#define ICE_REGS_PARAMETERS_5 0x0024
|
||||
|
||||
|
||||
/* QTI ICE v3.X only */
|
||||
#define ICE_GENERAL_ERR_STTS 0x0040
|
||||
#define ICE_INVALID_CCFG_ERR_STTS 0x0030
|
||||
#define ICE_GENERAL_ERR_MASK 0x0044
|
||||
|
||||
|
||||
/* QTI ICE v2.X only */
|
||||
#define ICE_REGS_NON_SEC_IRQ_STTS 0x0040
|
||||
#define ICE_REGS_NON_SEC_IRQ_MASK 0x0044
|
||||
|
||||
|
||||
#define ICE_REGS_NON_SEC_IRQ_CLR 0x0048
|
||||
#define ICE_REGS_STREAM1_ERROR_SYNDROME1 0x0050
|
||||
#define ICE_REGS_STREAM1_ERROR_SYNDROME2 0x0054
|
||||
#define ICE_REGS_STREAM2_ERROR_SYNDROME1 0x0058
|
||||
#define ICE_REGS_STREAM2_ERROR_SYNDROME2 0x005C
|
||||
#define ICE_REGS_STREAM1_BIST_ERROR_VEC 0x0060
|
||||
#define ICE_REGS_STREAM2_BIST_ERROR_VEC 0x0064
|
||||
#define ICE_REGS_STREAM1_BIST_FINISH_VEC 0x0068
|
||||
#define ICE_REGS_STREAM2_BIST_FINISH_VEC 0x006C
|
||||
#define ICE_REGS_BIST_STATUS 0x0070
|
||||
#define ICE_REGS_BYPASS_STATUS 0x0074
|
||||
#define ICE_REGS_ADVANCED_CONTROL 0x1000
|
||||
#define ICE_REGS_ENDIAN_SWAP 0x1004
|
||||
#define ICE_REGS_TEST_BUS_CONTROL 0x1010
|
||||
#define ICE_REGS_TEST_BUS_REG 0x1014
|
||||
#define ICE_REGS_STREAM1_COUNTERS1 0x1100
|
||||
#define ICE_REGS_STREAM1_COUNTERS2 0x1104
|
||||
#define ICE_REGS_STREAM1_COUNTERS3 0x1108
|
||||
#define ICE_REGS_STREAM1_COUNTERS4 0x110C
|
||||
#define ICE_REGS_STREAM1_COUNTERS5_MSB 0x1110
|
||||
#define ICE_REGS_STREAM1_COUNTERS5_LSB 0x1114
|
||||
#define ICE_REGS_STREAM1_COUNTERS6_MSB 0x1118
|
||||
#define ICE_REGS_STREAM1_COUNTERS6_LSB 0x111C
|
||||
#define ICE_REGS_STREAM1_COUNTERS7_MSB 0x1120
|
||||
#define ICE_REGS_STREAM1_COUNTERS7_LSB 0x1124
|
||||
#define ICE_REGS_STREAM1_COUNTERS8_MSB 0x1128
|
||||
#define ICE_REGS_STREAM1_COUNTERS8_LSB 0x112C
|
||||
#define ICE_REGS_STREAM1_COUNTERS9_MSB 0x1130
|
||||
#define ICE_REGS_STREAM1_COUNTERS9_LSB 0x1134
|
||||
#define ICE_REGS_STREAM2_COUNTERS1 0x1200
|
||||
#define ICE_REGS_STREAM2_COUNTERS2 0x1204
|
||||
#define ICE_REGS_STREAM2_COUNTERS3 0x1208
|
||||
#define ICE_REGS_STREAM2_COUNTERS4 0x120C
|
||||
#define ICE_REGS_STREAM2_COUNTERS5_MSB 0x1210
|
||||
#define ICE_REGS_STREAM2_COUNTERS5_LSB 0x1214
|
||||
#define ICE_REGS_STREAM2_COUNTERS6_MSB 0x1218
|
||||
#define ICE_REGS_STREAM2_COUNTERS6_LSB 0x121C
|
||||
#define ICE_REGS_STREAM2_COUNTERS7_MSB 0x1220
|
||||
#define ICE_REGS_STREAM2_COUNTERS7_LSB 0x1224
|
||||
#define ICE_REGS_STREAM2_COUNTERS8_MSB 0x1228
|
||||
#define ICE_REGS_STREAM2_COUNTERS8_LSB 0x122C
|
||||
#define ICE_REGS_STREAM2_COUNTERS9_MSB 0x1230
|
||||
#define ICE_REGS_STREAM2_COUNTERS9_LSB 0x1234
|
||||
|
||||
#define ICE_STREAM1_PREMATURE_LBA_CHANGE (1L << 0)
|
||||
#define ICE_STREAM2_PREMATURE_LBA_CHANGE (1L << 1)
|
||||
#define ICE_STREAM1_NOT_EXPECTED_LBO (1L << 2)
|
||||
#define ICE_STREAM2_NOT_EXPECTED_LBO (1L << 3)
|
||||
#define ICE_STREAM1_NOT_EXPECTED_DUN (1L << 4)
|
||||
#define ICE_STREAM2_NOT_EXPECTED_DUN (1L << 5)
|
||||
#define ICE_STREAM1_NOT_EXPECTED_DUS (1L << 6)
|
||||
#define ICE_STREAM2_NOT_EXPECTED_DUS (1L << 7)
|
||||
#define ICE_STREAM1_NOT_EXPECTED_DBO (1L << 8)
|
||||
#define ICE_STREAM2_NOT_EXPECTED_DBO (1L << 9)
|
||||
#define ICE_STREAM1_NOT_EXPECTED_ENC_SEL (1L << 10)
|
||||
#define ICE_STREAM2_NOT_EXPECTED_ENC_SEL (1L << 11)
|
||||
#define ICE_STREAM1_NOT_EXPECTED_CONF_IDX (1L << 12)
|
||||
#define ICE_STREAM2_NOT_EXPECTED_CONF_IDX (1L << 13)
|
||||
#define ICE_STREAM1_NOT_EXPECTED_NEW_TRNS (1L << 14)
|
||||
#define ICE_STREAM2_NOT_EXPECTED_NEW_TRNS (1L << 15)
|
||||
|
||||
#define ICE_NON_SEC_IRQ_MASK \
|
||||
(ICE_STREAM1_PREMATURE_LBA_CHANGE |\
|
||||
ICE_STREAM2_PREMATURE_LBA_CHANGE |\
|
||||
ICE_STREAM1_NOT_EXPECTED_LBO |\
|
||||
ICE_STREAM2_NOT_EXPECTED_LBO |\
|
||||
ICE_STREAM1_NOT_EXPECTED_DUN |\
|
||||
ICE_STREAM2_NOT_EXPECTED_DUN |\
|
||||
ICE_STREAM2_NOT_EXPECTED_DUS |\
|
||||
ICE_STREAM1_NOT_EXPECTED_DBO |\
|
||||
ICE_STREAM2_NOT_EXPECTED_DBO |\
|
||||
ICE_STREAM1_NOT_EXPECTED_ENC_SEL |\
|
||||
ICE_STREAM2_NOT_EXPECTED_ENC_SEL |\
|
||||
ICE_STREAM1_NOT_EXPECTED_CONF_IDX |\
|
||||
ICE_STREAM1_NOT_EXPECTED_NEW_TRNS |\
|
||||
ICE_STREAM2_NOT_EXPECTED_NEW_TRNS)
|
||||
|
||||
/* QTI ICE registers from secure side */
|
||||
#define ICE_TEST_BUS_REG_SECURE_INTR (1L << 28)
|
||||
#define ICE_TEST_BUS_REG_NON_SECURE_INTR (1L << 2)
|
||||
|
||||
#define ICE_LUT_KEYS_CRYPTOCFG_R_16 0x4040
|
||||
#define ICE_LUT_KEYS_CRYPTOCFG_R_17 0x4044
|
||||
#define ICE_LUT_KEYS_CRYPTOCFG_OFFSET 0x80
|
||||
|
||||
|
||||
#define ICE_LUT_KEYS_ICE_SEC_IRQ_STTS 0x6200
|
||||
#define ICE_LUT_KEYS_ICE_SEC_IRQ_MASK 0x6204
|
||||
#define ICE_LUT_KEYS_ICE_SEC_IRQ_CLR 0x6208
|
||||
|
||||
#define ICE_STREAM1_PARTIALLY_SET_KEY_USED (1L << 0)
|
||||
#define ICE_STREAM2_PARTIALLY_SET_KEY_USED (1L << 1)
|
||||
#define ICE_QTIC_DBG_OPEN_EVENT (1L << 30)
|
||||
#define ICE_KEYS_RAM_RESET_COMPLETED (1L << 31)
|
||||
|
||||
#define ICE_SEC_IRQ_MASK \
|
||||
(ICE_STREAM1_PARTIALLY_SET_KEY_USED |\
|
||||
ICE_STREAM2_PARTIALLY_SET_KEY_USED |\
|
||||
ICE_QTIC_DBG_OPEN_EVENT | \
|
||||
ICE_KEYS_RAM_RESET_COMPLETED)
|
||||
|
||||
#define ice_writel(ice_entry, val, reg) \
|
||||
writel_relaxed((val), (ice_entry)->icemmio_base + (reg))
|
||||
#define ice_readl(ice_entry, reg) \
|
||||
readl_relaxed((ice_entry)->icemmio_base + (reg))
|
||||
|
||||
#endif /* _CRYPTO_INLINE_CRYPTO_ENGINE_REGS_H_ */
|
||||
41
drivers/soc/qcom/crypto-qti-platform.h
Normal file
41
drivers/soc/qcom/crypto-qti-platform.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_QTI_PLATFORM_H
|
||||
#define _CRYPTO_QTI_PLATFORM_H
|
||||
|
||||
#include <linux/bio-crypt-ctx.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_QTI_CRYPTO_TZ)
|
||||
int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry,
|
||||
const struct blk_crypto_key *key,
|
||||
unsigned int slot,
|
||||
unsigned int data_unit_mask, int capid);
|
||||
int crypto_qti_invalidate_key(struct crypto_vops_qti_entry *ice_entry,
|
||||
unsigned int slot);
|
||||
#else
|
||||
static inline int crypto_qti_program_key(
|
||||
struct crypto_vops_qti_entry *ice_entry,
|
||||
const struct blk_crypto_key *key,
|
||||
unsigned int slot,
|
||||
unsigned int data_unit_mask, int capid)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int crypto_qti_invalidate_key(
|
||||
struct crypto_vops_qti_entry *ice_entry, unsigned int slot)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_QTI_CRYPTO_TZ */
|
||||
|
||||
static inline void crypto_qti_disable_platform(
|
||||
struct crypto_vops_qti_entry *ice_entry)
|
||||
{}
|
||||
|
||||
#endif /* _CRYPTO_QTI_PLATFORM_H */
|
||||
61
drivers/soc/qcom/crypto-qti-tz.c
Normal file
61
drivers/soc/qcom/crypto-qti-tz.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Crypto TZ library for storage encryption.
|
||||
*
|
||||
* Copyright (c) 2020, Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
#include <linux/qtee_shmbridge.h>
|
||||
#include <linux/crypto-qti-common.h>
|
||||
#include <linux/module.h>
|
||||
#include "crypto-qti-platform.h"
|
||||
|
||||
#define ICE_CIPHER_MODE_XTS_256 3
|
||||
#define UFS_CE 10
|
||||
#define SDCC_CE 20
|
||||
#define UFS_CARD_CE 30
|
||||
|
||||
int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry,
|
||||
const struct blk_crypto_key *key, unsigned int slot,
|
||||
unsigned int data_unit_mask, int capid)
|
||||
{
|
||||
int err = 0;
|
||||
struct qtee_shm shm;
|
||||
|
||||
err = qtee_shmbridge_allocate_shm(key->size, &shm);
|
||||
if (err)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(shm.vaddr, key->raw, key->size);
|
||||
qtee_shmbridge_flush_shm_buf(&shm);
|
||||
|
||||
err = qcom_scm_config_set_ice_key(slot, shm.paddr, shm.size,
|
||||
ICE_CIPHER_MODE_XTS_256, data_unit_mask, UFS_CE);
|
||||
if (err)
|
||||
pr_err("%s:SCM call Error: 0x%x slot %d\n",
|
||||
__func__, err, slot);
|
||||
|
||||
qtee_shmbridge_inv_shm_buf(&shm);
|
||||
qtee_shmbridge_free_shm(&shm);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_program_key);
|
||||
|
||||
int crypto_qti_invalidate_key(struct crypto_vops_qti_entry *ice_entry,
|
||||
unsigned int slot)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = qcom_scm_clear_ice_key(slot, UFS_CE);
|
||||
if (err)
|
||||
pr_err("%s:SCM call Error: 0x%x\n", __func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_qti_invalidate_key);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Crypto TZ library for storage encryption");
|
||||
87
include/linux/crypto-qti-common.h
Normal file
87
include/linux/crypto-qti-common.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_QTI_COMMON_H
|
||||
#define _CRYPTO_QTI_COMMON_H
|
||||
|
||||
#include <linux/bio-crypt-ctx.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define RAW_SECRET_SIZE 32
|
||||
#define QTI_ICE_MAX_BIST_CHECK_COUNT 100
|
||||
#define QTI_ICE_TYPE_NAME_LEN 8
|
||||
|
||||
struct crypto_vops_qti_entry {
|
||||
void __iomem *icemmio_base;
|
||||
uint32_t ice_hw_version;
|
||||
uint8_t ice_dev_type[QTI_ICE_TYPE_NAME_LEN];
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_QTI_CRYPTO_COMMON)
|
||||
int crypto_qti_init_crypto(struct device *dev, void __iomem *mmio_base,
|
||||
void **priv_data);
|
||||
int crypto_qti_enable(void *priv_data);
|
||||
void crypto_qti_disable(void *priv_data);
|
||||
int crypto_qti_resume(void *priv_data);
|
||||
int crypto_qti_debug(void *priv_data);
|
||||
int crypto_qti_keyslot_program(void *priv_data,
|
||||
const struct blk_crypto_key *key,
|
||||
unsigned int slot, u8 data_unit_mask,
|
||||
int capid);
|
||||
int crypto_qti_keyslot_evict(void *priv_data, unsigned int slot);
|
||||
int crypto_qti_derive_raw_secret(const u8 *wrapped_key,
|
||||
unsigned int wrapped_key_size, u8 *secret,
|
||||
unsigned int secret_size);
|
||||
|
||||
#else
|
||||
static inline int crypto_qti_init_crypto(struct device *dev,
|
||||
void __iomem *mmio_base,
|
||||
void **priv_data)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int crypto_qti_enable(void *priv_data)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline void crypto_qti_disable(void *priv_data)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int crypto_qti_resume(void *priv_data)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int crypto_qti_debug(void *priv_data)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int crypto_qti_keyslot_program(void *priv_data,
|
||||
const struct blk_crypto_key *key,
|
||||
unsigned int slot,
|
||||
u8 data_unit_mask,
|
||||
int capid)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int crypto_qti_keyslot_evict(void *priv_data, unsigned int slot)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int crypto_qti_derive_raw_secret(const u8 *wrapped_key,
|
||||
unsigned int wrapped_key_size,
|
||||
u8 *secret,
|
||||
unsigned int secret_size)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_QTI_CRYPTO_COMMON */
|
||||
|
||||
#endif /* _CRYPTO_QTI_COMMON_H */
|
||||
Loading…
Reference in a new issue