linux/drivers/scsi/ufs/ufs-qcom-ice.c
<<
>>
Prefs
   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/platform_device.h>
  10#include <linux/qcom_scm.h>
  11
  12#include "ufshcd-crypto.h"
  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}
 246