ufs-qcom-ice.c (6790B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Qualcomm ICE (Inline Crypto Engine) support. 4 * 5 * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. 6 * Copyright 2019 Google LLC 7 */ 8 9#include <linux/delay.h> 10#include <linux/platform_device.h> 11#include <linux/qcom_scm.h> 12 13#include "ufs-qcom.h" 14 15#define AES_256_XTS_KEY_SIZE 64 16 17/* QCOM ICE registers */ 18 19#define QCOM_ICE_REG_CONTROL 0x0000 20#define QCOM_ICE_REG_RESET 0x0004 21#define QCOM_ICE_REG_VERSION 0x0008 22#define QCOM_ICE_REG_FUSE_SETTING 0x0010 23#define QCOM_ICE_REG_PARAMETERS_1 0x0014 24#define QCOM_ICE_REG_PARAMETERS_2 0x0018 25#define QCOM_ICE_REG_PARAMETERS_3 0x001C 26#define QCOM_ICE_REG_PARAMETERS_4 0x0020 27#define QCOM_ICE_REG_PARAMETERS_5 0x0024 28 29/* QCOM ICE v3.X only */ 30#define QCOM_ICE_GENERAL_ERR_STTS 0x0040 31#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030 32#define QCOM_ICE_GENERAL_ERR_MASK 0x0044 33 34/* QCOM ICE v2.X only */ 35#define QCOM_ICE_REG_NON_SEC_IRQ_STTS 0x0040 36#define QCOM_ICE_REG_NON_SEC_IRQ_MASK 0x0044 37 38#define QCOM_ICE_REG_NON_SEC_IRQ_CLR 0x0048 39#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME1 0x0050 40#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME2 0x0054 41#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME1 0x0058 42#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME2 0x005C 43#define QCOM_ICE_REG_STREAM1_BIST_ERROR_VEC 0x0060 44#define QCOM_ICE_REG_STREAM2_BIST_ERROR_VEC 0x0064 45#define QCOM_ICE_REG_STREAM1_BIST_FINISH_VEC 0x0068 46#define QCOM_ICE_REG_STREAM2_BIST_FINISH_VEC 0x006C 47#define QCOM_ICE_REG_BIST_STATUS 0x0070 48#define QCOM_ICE_REG_BYPASS_STATUS 0x0074 49#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 50#define QCOM_ICE_REG_ENDIAN_SWAP 0x1004 51#define QCOM_ICE_REG_TEST_BUS_CONTROL 0x1010 52#define QCOM_ICE_REG_TEST_BUS_REG 0x1014 53 54/* BIST ("built-in self-test"?) status flags */ 55#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000 56 57#define QCOM_ICE_FUSE_SETTING_MASK 0x1 58#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 59#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 60 61#define qcom_ice_writel(host, val, reg) \ 62 writel((val), (host)->ice_mmio + (reg)) 63#define qcom_ice_readl(host, reg) \ 64 readl((host)->ice_mmio + (reg)) 65 66static bool qcom_ice_supported(struct ufs_qcom_host *host) 67{ 68 struct device *dev = host->hba->dev; 69 u32 regval = qcom_ice_readl(host, QCOM_ICE_REG_VERSION); 70 int major = regval >> 24; 71 int minor = (regval >> 16) & 0xFF; 72 int step = regval & 0xFFFF; 73 74 /* For now this driver only supports ICE version 3. */ 75 if (major != 3) { 76 dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n", 77 major, minor, step); 78 return false; 79 } 80 81 dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", 82 major, minor, step); 83 84 /* If fuses are blown, ICE might not work in the standard way. */ 85 regval = qcom_ice_readl(host, QCOM_ICE_REG_FUSE_SETTING); 86 if (regval & (QCOM_ICE_FUSE_SETTING_MASK | 87 QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK | 88 QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) { 89 dev_warn(dev, "Fuses are blown; ICE is unusable!\n"); 90 return false; 91 } 92 return true; 93} 94 95int ufs_qcom_ice_init(struct ufs_qcom_host *host) 96{ 97 struct ufs_hba *hba = host->hba; 98 struct device *dev = hba->dev; 99 struct platform_device *pdev = to_platform_device(dev); 100 struct resource *res; 101 int err; 102 103 if (!(ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES) & 104 MASK_CRYPTO_SUPPORT)) 105 return 0; 106 107 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"); 108 if (!res) { 109 dev_warn(dev, "ICE registers not found\n"); 110 goto disable; 111 } 112 113 if (!qcom_scm_ice_available()) { 114 dev_warn(dev, "ICE SCM interface not found\n"); 115 goto disable; 116 } 117 118 host->ice_mmio = devm_ioremap_resource(dev, res); 119 if (IS_ERR(host->ice_mmio)) { 120 err = PTR_ERR(host->ice_mmio); 121 dev_err(dev, "Failed to map ICE registers; err=%d\n", err); 122 return err; 123 } 124 125 if (!qcom_ice_supported(host)) 126 goto disable; 127 128 return 0; 129 130disable: 131 dev_warn(dev, "Disabling inline encryption support\n"); 132 hba->caps &= ~UFSHCD_CAP_CRYPTO; 133 return 0; 134} 135 136static void qcom_ice_low_power_mode_enable(struct ufs_qcom_host *host) 137{ 138 u32 regval; 139 140 regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); 141 /* 142 * Enable low power mode sequence 143 * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0 144 */ 145 regval |= 0x7000; 146 qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); 147} 148 149static void qcom_ice_optimization_enable(struct ufs_qcom_host *host) 150{ 151 u32 regval; 152 153 /* ICE Optimizations Enable Sequence */ 154 regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); 155 regval |= 0xD807100; 156 /* ICE HPG requires delay before writing */ 157 udelay(5); 158 qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); 159 udelay(5); 160} 161 162int ufs_qcom_ice_enable(struct ufs_qcom_host *host) 163{ 164 if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) 165 return 0; 166 qcom_ice_low_power_mode_enable(host); 167 qcom_ice_optimization_enable(host); 168 return ufs_qcom_ice_resume(host); 169} 170 171/* Poll until all BIST bits are reset */ 172static int qcom_ice_wait_bist_status(struct ufs_qcom_host *host) 173{ 174 int count; 175 u32 reg; 176 177 for (count = 0; count < 100; count++) { 178 reg = qcom_ice_readl(host, QCOM_ICE_REG_BIST_STATUS); 179 if (!(reg & QCOM_ICE_BIST_STATUS_MASK)) 180 break; 181 udelay(50); 182 } 183 if (reg) 184 return -ETIMEDOUT; 185 return 0; 186} 187 188int ufs_qcom_ice_resume(struct ufs_qcom_host *host) 189{ 190 int err; 191 192 if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) 193 return 0; 194 195 err = qcom_ice_wait_bist_status(host); 196 if (err) { 197 dev_err(host->hba->dev, "BIST status error (%d)\n", err); 198 return err; 199 } 200 return 0; 201} 202 203/* 204 * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires 205 * vendor-specific SCM calls for this; it doesn't support the standard way. 206 */ 207int ufs_qcom_ice_program_key(struct ufs_hba *hba, 208 const union ufs_crypto_cfg_entry *cfg, int slot) 209{ 210 union ufs_crypto_cap_entry cap; 211 union { 212 u8 bytes[AES_256_XTS_KEY_SIZE]; 213 u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)]; 214 } key; 215 int i; 216 int err; 217 218 if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) 219 return qcom_scm_ice_invalidate_key(slot); 220 221 /* Only AES-256-XTS has been tested so far. */ 222 cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; 223 if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || 224 cap.key_size != UFS_CRYPTO_KEY_SIZE_256) { 225 dev_err_ratelimited(hba->dev, 226 "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n", 227 cap.algorithm_id, cap.key_size); 228 return -EINVAL; 229 } 230 231 memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE); 232 233 /* 234 * The SCM call byte-swaps the 32-bit words of the key. So we have to 235 * do the same, in order for the final key be correct. 236 */ 237 for (i = 0; i < ARRAY_SIZE(key.words); i++) 238 __cpu_to_be32s(&key.words[i]); 239 240 err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE, 241 QCOM_SCM_ICE_CIPHER_AES_256_XTS, 242 cfg->data_unit_size); 243 memzero_explicit(&key, sizeof(key)); 244 return err; 245}