@@ -216,4 +216,11 @@ config QTI_ICE_COMMON
help
Enable the common ICE library that can be used
by UFS and EMMC drivers for ICE functionality.
+
+config QTI_HW_WRAPPED_KEYS
+ tristate "QTI HW Wrapped Keys"
+ depends on QTI_ICE_COMMON
+ help
+ Enable wrapped key functionality for storage
+ encryption.
endmenu
@@ -27,3 +27,4 @@ obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o
obj-$(CONFIG_QTI_ICE_COMMON) += qti-ice-common.o
+obj-$(CONFIG_QTI_HW_WRAPPED_KEYS) += qti-ice-hwkm.o
new file mode 100644
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HWKM ICE library for storage encryption.
+ *
+ * Copyright (c) 2021, Linux Foundation. All rights reserved.
+ */
+
+#include <linux/qti-ice-common.h>
+#include "qti-ice-regs.h"
+
+static int qti_ice_hwkm_bist_status(const struct ice_mmio_data *mmio, int version)
+{
+ if (!qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+ (version == 1) ? BIST_DONE_V1 : BIST_DONE_V2) ||
+ !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+ (version == 1) ? CRYPTO_LIB_BIST_DONE_V1 :
+ CRYPTO_LIB_BIST_DONE_V2) ||
+ !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+ (version == 1) ? BOOT_CMD_LIST1_DONE_V1 :
+ BOOT_CMD_LIST1_DONE_V2) ||
+ !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+ (version == 1) ? BOOT_CMD_LIST0_DONE_V1 :
+ BOOT_CMD_LIST0_DONE_V2) ||
+ !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+ (version == 1) ? KT_CLEAR_DONE_V1 :
+ KT_CLEAR_DONE_V2))
+ return -EINVAL;
+ return 0;
+}
+
+static int qti_ice_hwkm_init_sequence(const struct ice_mmio_data *mmio,
+ int version)
+{
+ u32 val = 0;
+
+ /*
+ * Put ICE in standard mode, ICE defaults to legacy mode.
+ * Legacy mode - ICE HWKM slave not supported.
+ * Standard mode - ICE HWKM slave supported.
+ *
+ * Depending on the version of HWKM, it is controlled by different
+ * registers in ICE.
+ */
+ if (version >= 2) {
+ val = qti_ice_readl(mmio->ice_mmio, QTI_ICE_REGS_CONTROL);
+ val = val & 0xFFFFFFFE;
+ qti_ice_writel(mmio->ice_mmio, val, QTI_ICE_REGS_CONTROL);
+ } else {
+ qti_ice_hwkm_writel(mmio->ice_hwkm_mmio, 0x7,
+ QTI_HWKM_ICE_RG_TZ_KM_CTL);
+ }
+
+ /* Check BIST status */
+ if (qti_ice_hwkm_bist_status(mmio, version))
+ return -EINVAL;
+
+ /* Disable CRC check */
+ qti_ice_hwkm_clearb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_CTL,
+ CRC_CHECK_EN);
+
+ /* Set RSP_FIFO_FULL bit */
+ qti_ice_hwkm_setb(mmio->ice_hwkm_mmio,
+ QTI_HWKM_ICE_RG_BANK0_BANKN_IRQ_STATUS, RSP_FIFO_FULL);
+
+ return 0;
+}
+
+int qti_ice_hwkm_init(const struct ice_mmio_data *mmio, int version)
+{
+ if (!mmio->ice_hwkm_mmio)
+ return -EINVAL;
+
+ return qti_ice_hwkm_init_sequence(mmio, version);
+}
+EXPORT_SYMBOL(qti_ice_hwkm_init);
+
+MODULE_LICENSE("GPL v2");
@@ -137,9 +137,121 @@
QTI_ICE_QTIC_DBG_OPEN_EVENT | \
QTI_ICE_KEYS_RAM_RESET_COMPLETED)
+/* Read/write macros for ICE address space */
#define qti_ice_writel(mmio, val, reg) \
writel_relaxed((val), mmio + (reg))
#define qti_ice_readl(mmio, reg) \
readl_relaxed(mmio + (reg))
+/* Registers for ICE HWKM Slave */
+
+#define HWKM_VERSION_STEP_REV_MASK 0xFFFF
+#define HWKM_VERSION_STEP_REV 0 /* bit 15-0 */
+#define HWKM_VERSION_MAJOR_REV_MASK 0xFF000000
+#define HWKM_VERSION_MAJOR_REV 24 /* bit 31-24 */
+#define HWKM_VERSION_MINOR_REV_MASK 0xFF0000
+#define HWKM_VERSION_MINOR_REV 16 /* bit 23-16 */
+
+/* QTI HWKM ICE slave config and status registers */
+
+#define QTI_HWKM_ICE_RG_IPCAT_VERSION 0x0000
+#define QTI_HWKM_ICE_RG_KEY_POLICY_VERSION 0x0004
+#define QTI_HWKM_ICE_RG_SHARED_STATUS 0x0008
+#define QTI_HWKM_ICE_RG_KEYTABLE_SIZE 0x000C
+
+#define QTI_HWKM_ICE_RG_TZ_KM_CTL 0x1000
+#define QTI_HWKM_ICE_RG_TZ_KM_STATUS 0x1004
+#define QTI_HWKM_ICE_RG_TZ_KM_STATUS_IRQ_MASK 0x1008
+#define QTI_HWKM_ICE_RG_TZ_KM_BOOT_STAGE_OTP 0x100C
+#define QTI_HWKM_ICE_RG_TZ_KM_DEBUG_CTL 0x1010
+#define QTI_HWKM_ICE_RG_TZ_KM_DEBUG_WRITE 0x1014
+#define QTI_HWKM_ICE_RG_TZ_KM_DEBUG_READ 0x1018
+#define QTI_HWKM_ICE_RG_TZ_TPKEY_RECEIVE_CTL 0x101C
+#define QTI_HWKM_ICE_RG_TZ_TPKEY_RECEIVE_STATUS 0x1020
+#define QTI_HWKM_ICE_RG_TZ_KM_COMMON_IRQ_ROUTING 0x1024
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_KM_CTL */
+#define CRC_CHECK_EN 0
+#define KEYTABLE_HW_WR_ACCESS_EN 1
+#define KEYTABLE_HW_RD_ACCESS_EN 2
+#define BOOT_INIT0_DISABLE 3
+#define BOOT_INIT1_DISABLE 4
+#define ICE_LEGACY_MODE_EN_OTP 5
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_KM_STATUS for v2 and above*/
+#define KT_CLEAR_DONE_V2 0
+#define BOOT_CMD_LIST0_DONE_V2 1
+#define BOOT_CMD_LIST1_DONE_V2 2
+#define LAST_ACTIVITY_BANK_V2 3
+#define CRYPTO_LIB_BIST_ERROR_V2 6
+#define CRYPTO_LIB_BIST_DONE_V2 7
+#define BIST_ERROR_V2 8
+#define BIST_DONE_V2 9
+#define LAST_ACTIVITY_BANK_MASK_V2 0x38
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_KM_STATUS for v1*/
+#define KT_CLEAR_DONE_V1 0
+#define BOOT_CMD_LIST0_DONE_V1 1
+#define BOOT_CMD_LIST1_DONE_V1 2
+#define KEYTABLE_KEY_POLICY_V1 3
+#define KEYTABLE_INTEGRITY_ERROR_V1 4
+#define KEYTABLE_KEY_SLOT_ERROR_V1 5
+#define KEYTABLE_KEY_SLOT_NOT_EVEN_ERROR_V1 6
+#define KEYTABLE_KEY_SLOT_OUT_OF_RANGE_V1 7
+#define KEYTABLE_KEY_SIZE_ERROR_V1 8
+#define KEYTABLE_OPERATION_ERROR_V1 9
+#define LAST_ACTIVITY_BANK_V1 10
+#define CRYPTO_LIB_BIST_ERROR_V1 13
+#define CRYPTO_LIB_BIST_DONE_V1 14
+#define BIST_ERROR_V1 15
+#define BIST_DONE_V1 16
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_TPKEY_RECEIVE_CTL */
+#define TPKEY_EN 8
+
+/* QTI HWKM ICE slave register bank 0 */
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_CTL 0x2000
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_STATUS 0x2004
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_IRQ_STATUS 0x2008
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_IRQ_MASK 0x200C
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_ESR 0x2010
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_ESR_IRQ_MASK 0x2014
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_ESYNR 0x2018
+
+/* QTI_HWKM_ICE_RG_BANKN_IRQ_STATUS */
+#define ARB_GRAN_WINNER 0
+#define CMD_DONE_BIT 1
+#define RSP_FIFO_NOT_EMPTY 2
+#define RSP_FIFO_FULL 3
+#define RSP_FIFO_UNDERFLOW 4
+#define CMD_FIFO_UNDERFLOW 5
+
+/* Read/write macros for ICE HWKM address space */
+
+#define qti_ice_hwkm_readl(hwkm_mmio, reg) \
+ (readl_relaxed(hwkm_mmio + (reg)))
+#define qti_ice_hwkm_writel(hwkm_mmio, val, reg) \
+ (writel_relaxed((val), hwkm_mmio + (reg)))
+#define qti_ice_hwkm_setb(hwkm_mmio, reg, nr) { \
+ u32 val = qti_ice_hwkm_readl(hwkm_mmio, reg); \
+ val |= (0x1 << nr); \
+ qti_ice_hwkm_writel(hwkm_mmio, val, reg); \
+}
+#define qti_ice_hwkm_clearb(hwkm_mmio, reg, nr) { \
+ u32 val = qti_ice_hwkm_readl(hwkm_mmio, reg); \
+ val &= ~(0x1 << nr); \
+ qti_ice_hwkm_writel(hwkm_mmio, val, reg); \
+}
+
+static inline bool qti_ice_hwkm_testb(void __iomem *ice_hwkm_mmio,
+ u32 reg, u8 nr)
+{
+ u32 val = qti_ice_hwkm_readl(ice_hwkm_mmio, reg);
+
+ val = (val >> nr) & 0x1;
+ if (val == 0)
+ return false;
+ return true;
+}
+
#endif /* _QTI_INLINE_CRYPTO_ENGINE_REGS_H_ */
@@ -23,4 +23,10 @@ int qti_ice_keyslot_program(const struct ice_mmio_data *mmio,
unsigned int slot, u8 data_unit_mask, int capid);
int qti_ice_keyslot_evict(unsigned int slot);
+#if IS_ENABLED(CONFIG_QTI_HW_WRAPPED_KEYS)
+int qti_ice_hwkm_init(const struct ice_mmio_data *mmio, int version);
+#else
+static inline int qti_ice_hwkm_init(const struct ice_mmio_data *mmio,
+ int version) { return -ENODEV; }
+#endif /* CONFIG_QTI_HW_WRAPPED_KEYS */
#endif /* _QTI_ICE_COMMON_H */
Wrapped keys should utilize hardware to protect the keys used for storage encryption. Qualcomm's Inline Crypto Engine supports a hardware block called Hardware Key Manager (HWKM) for key management. Although most of the interactions to this hardware block happens via a secure execution environment, some initializations for the slave present in ICE can be done from the kernel. This can also be a placeholder for when the hardware provides more capabilites to be acessed from the linux kernel in the future. Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com> --- drivers/soc/qcom/Kconfig | 7 ++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/qti-ice-hwkm.c | 77 ++++++++++++++++++++++ drivers/soc/qcom/qti-ice-regs.h | 112 ++++++++++++++++++++++++++++++++ include/linux/qti-ice-common.h | 6 ++ 5 files changed, 203 insertions(+) create mode 100644 drivers/soc/qcom/qti-ice-hwkm.c