8
8
*
9
9
*/
10
10
11
+ #include <asm/unaligned.h>
12
+ #include <crypto/aes.h>
13
+ #include <linux/arm-smccc.h>
11
14
#include <linux/clk.h>
12
15
#include <linux/delay.h>
13
16
#include <linux/module.h>
25
28
26
29
#include "ufs-exynos.h"
27
30
31
+ #define DATA_UNIT_SIZE 4096
32
+
28
33
/*
29
34
* Exynos's Vendor specific registers for UFSHCI
30
35
*/
31
36
#define HCI_TXPRDT_ENTRY_SIZE 0x00
32
37
#define PRDT_PREFECT_EN BIT(31)
33
- #define PRDT_SET_SIZE (x ) ((x) & 0x1F)
34
38
#define HCI_RXPRDT_ENTRY_SIZE 0x04
35
39
#define HCI_1US_TO_CNT_VAL 0x0C
36
40
#define CNT_VAL_1US_MASK 0x3FF
@@ -1043,8 +1047,8 @@ static int exynos_ufs_post_link(struct ufs_hba *hba)
1043
1047
exynos_ufs_fit_aggr_timeout (ufs );
1044
1048
1045
1049
hci_writel (ufs , 0xa , HCI_DATA_REORDER );
1046
- hci_writel (ufs , PRDT_SET_SIZE ( 12 ), HCI_TXPRDT_ENTRY_SIZE );
1047
- hci_writel (ufs , PRDT_SET_SIZE ( 12 ), HCI_RXPRDT_ENTRY_SIZE );
1050
+ hci_writel (ufs , ilog2 ( DATA_UNIT_SIZE ), HCI_TXPRDT_ENTRY_SIZE );
1051
+ hci_writel (ufs , ilog2 ( DATA_UNIT_SIZE ), HCI_RXPRDT_ENTRY_SIZE );
1048
1052
hci_writel (ufs , (1 << hba -> nutrs ) - 1 , HCI_UTRL_NEXUS_TYPE );
1049
1053
hci_writel (ufs , (1 << hba -> nutmrs ) - 1 , HCI_UTMRL_NEXUS_TYPE );
1050
1054
hci_writel (ufs , 0xf , HCI_AXIDMA_RWDATA_BURST_LEN );
@@ -1151,6 +1155,227 @@ static inline void exynos_ufs_priv_init(struct ufs_hba *hba,
1151
1155
hba -> quirks = ufs -> drv_data -> quirks ;
1152
1156
}
1153
1157
1158
+ #ifdef CONFIG_SCSI_UFS_CRYPTO
1159
+
1160
+ /*
1161
+ * Support for Flash Memory Protector (FMP), which is the inline encryption
1162
+ * hardware on Exynos and Exynos-based SoCs. The interface to this hardware is
1163
+ * not compatible with the standard UFS crypto. It requires that encryption be
1164
+ * configured in the PRDT using a nonstandard extension.
1165
+ */
1166
+
1167
+ enum fmp_crypto_algo_mode {
1168
+ FMP_BYPASS_MODE = 0 ,
1169
+ FMP_ALGO_MODE_AES_CBC = 1 ,
1170
+ FMP_ALGO_MODE_AES_XTS = 2 ,
1171
+ };
1172
+ enum fmp_crypto_key_length {
1173
+ FMP_KEYLEN_256BIT = 1 ,
1174
+ };
1175
+
1176
+ /**
1177
+ * struct fmp_sg_entry - nonstandard format of PRDT entries when FMP is enabled
1178
+ *
1179
+ * @base: The standard PRDT entry, but with nonstandard bitfields in the high
1180
+ * bits of the 'size' field, i.e. the last 32-bit word. When these
1181
+ * nonstandard bitfields are zero, the data segment won't be encrypted or
1182
+ * decrypted. Otherwise they specify the algorithm and key length with
1183
+ * which the data segment will be encrypted or decrypted.
1184
+ * @file_iv: The initialization vector (IV) with all bytes reversed
1185
+ * @file_enckey: The first half of the AES-XTS key with all bytes reserved
1186
+ * @file_twkey: The second half of the AES-XTS key with all bytes reserved
1187
+ * @disk_iv: Unused
1188
+ * @reserved: Unused
1189
+ */
1190
+ struct fmp_sg_entry {
1191
+ struct ufshcd_sg_entry base ;
1192
+ __be64 file_iv [2 ];
1193
+ __be64 file_enckey [4 ];
1194
+ __be64 file_twkey [4 ];
1195
+ __be64 disk_iv [2 ];
1196
+ __be64 reserved [2 ];
1197
+ };
1198
+
1199
+ #define SMC_CMD_FMP_SECURITY \
1200
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
1201
+ ARM_SMCCC_OWNER_SIP, 0x1810)
1202
+ #define SMC_CMD_SMU \
1203
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
1204
+ ARM_SMCCC_OWNER_SIP, 0x1850)
1205
+ #define SMC_CMD_FMP_SMU_RESUME \
1206
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
1207
+ ARM_SMCCC_OWNER_SIP, 0x1860)
1208
+ #define SMU_EMBEDDED 0
1209
+ #define SMU_INIT 0
1210
+ #define CFG_DESCTYPE_3 3
1211
+
1212
+ static void exynos_ufs_fmp_init (struct ufs_hba * hba , struct exynos_ufs * ufs )
1213
+ {
1214
+ struct blk_crypto_profile * profile = & hba -> crypto_profile ;
1215
+ struct arm_smccc_res res ;
1216
+ int err ;
1217
+
1218
+ /*
1219
+ * Check for the standard crypto support bit, since it's available even
1220
+ * though the rest of the interface to FMP is nonstandard.
1221
+ *
1222
+ * This check should have the effect of preventing the driver from
1223
+ * trying to use FMP on old Exynos SoCs that don't have FMP.
1224
+ */
1225
+ if (!(ufshcd_readl (hba , REG_CONTROLLER_CAPABILITIES ) &
1226
+ MASK_CRYPTO_SUPPORT ))
1227
+ return ;
1228
+
1229
+ /*
1230
+ * The below sequence of SMC calls to enable FMP can be found in the
1231
+ * downstream driver source for gs101 and other Exynos-based SoCs. It
1232
+ * is the only way to enable FMP that works on SoCs such as gs101 that
1233
+ * don't make the FMP registers accessible to Linux. It probably works
1234
+ * on other Exynos-based SoCs too, and might even still be the only way
1235
+ * that works. But this hasn't been properly tested, and this code is
1236
+ * mutually exclusive with exynos_ufs_config_smu(). So for now only
1237
+ * enable FMP support on SoCs with EXYNOS_UFS_OPT_UFSPR_SECURE.
1238
+ */
1239
+ if (!(ufs -> opts & EXYNOS_UFS_OPT_UFSPR_SECURE ))
1240
+ return ;
1241
+
1242
+ /*
1243
+ * This call (which sets DESCTYPE to 0x3 in the FMPSECURITY0 register)
1244
+ * is needed to make the hardware use the larger PRDT entry size.
1245
+ */
1246
+ BUILD_BUG_ON (sizeof (struct fmp_sg_entry ) != 128 );
1247
+ arm_smccc_smc (SMC_CMD_FMP_SECURITY , 0 , SMU_EMBEDDED , CFG_DESCTYPE_3 ,
1248
+ 0 , 0 , 0 , 0 , & res );
1249
+ if (res .a0 ) {
1250
+ dev_warn (hba -> dev ,
1251
+ "SMC_CMD_FMP_SECURITY failed on init: %ld. Disabling FMP support.\n" ,
1252
+ res .a0 );
1253
+ return ;
1254
+ }
1255
+ ufshcd_set_sg_entry_size (hba , sizeof (struct fmp_sg_entry ));
1256
+
1257
+ /*
1258
+ * This is needed to initialize FMP. Without it, errors occur when
1259
+ * inline encryption is used.
1260
+ */
1261
+ arm_smccc_smc (SMC_CMD_SMU , SMU_INIT , SMU_EMBEDDED , 0 , 0 , 0 , 0 , 0 , & res );
1262
+ if (res .a0 ) {
1263
+ dev_err (hba -> dev ,
1264
+ "SMC_CMD_SMU(SMU_INIT) failed: %ld. Disabling FMP support.\n" ,
1265
+ res .a0 );
1266
+ return ;
1267
+ }
1268
+
1269
+ /* Advertise crypto capabilities to the block layer. */
1270
+ err = devm_blk_crypto_profile_init (hba -> dev , profile , 0 );
1271
+ if (err ) {
1272
+ /* Only ENOMEM should be possible here. */
1273
+ dev_err (hba -> dev , "Failed to initialize crypto profile: %d\n" ,
1274
+ err );
1275
+ return ;
1276
+ }
1277
+ profile -> max_dun_bytes_supported = AES_BLOCK_SIZE ;
1278
+ profile -> dev = hba -> dev ;
1279
+ profile -> modes_supported [BLK_ENCRYPTION_MODE_AES_256_XTS ] =
1280
+ DATA_UNIT_SIZE ;
1281
+
1282
+ /* Advertise crypto support to ufshcd-core. */
1283
+ hba -> caps |= UFSHCD_CAP_CRYPTO ;
1284
+
1285
+ /* Advertise crypto quirks to ufshcd-core. */
1286
+ hba -> quirks |= UFSHCD_QUIRK_CUSTOM_CRYPTO_PROFILE |
1287
+ UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE |
1288
+ UFSHCD_QUIRK_KEYS_IN_PRDT ;
1289
+
1290
+ }
1291
+
1292
+ static void exynos_ufs_fmp_resume (struct ufs_hba * hba )
1293
+ {
1294
+ struct arm_smccc_res res ;
1295
+
1296
+ arm_smccc_smc (SMC_CMD_FMP_SECURITY , 0 , SMU_EMBEDDED , CFG_DESCTYPE_3 ,
1297
+ 0 , 0 , 0 , 0 , & res );
1298
+ if (res .a0 )
1299
+ dev_err (hba -> dev ,
1300
+ "SMC_CMD_FMP_SECURITY failed on resume: %ld\n" , res .a0 );
1301
+
1302
+ arm_smccc_smc (SMC_CMD_FMP_SMU_RESUME , 0 , SMU_EMBEDDED , 0 , 0 , 0 , 0 , 0 ,
1303
+ & res );
1304
+ if (res .a0 )
1305
+ dev_err (hba -> dev ,
1306
+ "SMC_CMD_FMP_SMU_RESUME failed: %ld\n" , res .a0 );
1307
+ }
1308
+
1309
+ static inline __be64 fmp_key_word (const u8 * key , int j )
1310
+ {
1311
+ return cpu_to_be64 (get_unaligned_le64 (
1312
+ key + AES_KEYSIZE_256 - (j + 1 ) * sizeof (u64 )));
1313
+ }
1314
+
1315
+ /* Fill the PRDT for a request according to the given encryption context. */
1316
+ static int exynos_ufs_fmp_fill_prdt (struct ufs_hba * hba ,
1317
+ const struct bio_crypt_ctx * crypt_ctx ,
1318
+ void * prdt , unsigned int num_segments )
1319
+ {
1320
+ struct fmp_sg_entry * fmp_prdt = prdt ;
1321
+ const u8 * enckey = crypt_ctx -> bc_key -> raw ;
1322
+ const u8 * twkey = enckey + AES_KEYSIZE_256 ;
1323
+ u64 dun_lo = crypt_ctx -> bc_dun [0 ];
1324
+ u64 dun_hi = crypt_ctx -> bc_dun [1 ];
1325
+ unsigned int i ;
1326
+
1327
+ /* If FMP wasn't enabled, we shouldn't get any encrypted requests. */
1328
+ if (WARN_ON_ONCE (!(hba -> caps & UFSHCD_CAP_CRYPTO )))
1329
+ return - EIO ;
1330
+
1331
+ /* Configure FMP on each segment of the request. */
1332
+ for (i = 0 ; i < num_segments ; i ++ ) {
1333
+ struct fmp_sg_entry * prd = & fmp_prdt [i ];
1334
+ int j ;
1335
+
1336
+ /* Each segment must be exactly one data unit. */
1337
+ if (prd -> base .size != cpu_to_le32 (DATA_UNIT_SIZE - 1 )) {
1338
+ dev_err (hba -> dev ,
1339
+ "data segment is misaligned for FMP\n" );
1340
+ return - EIO ;
1341
+ }
1342
+
1343
+ /* Set the algorithm and key length. */
1344
+ prd -> base .size |= cpu_to_le32 ((FMP_ALGO_MODE_AES_XTS << 28 ) |
1345
+ (FMP_KEYLEN_256BIT << 26 ));
1346
+
1347
+ /* Set the IV. */
1348
+ prd -> file_iv [0 ] = cpu_to_be64 (dun_hi );
1349
+ prd -> file_iv [1 ] = cpu_to_be64 (dun_lo );
1350
+
1351
+ /* Set the key. */
1352
+ for (j = 0 ; j < AES_KEYSIZE_256 / sizeof (u64 ); j ++ ) {
1353
+ prd -> file_enckey [j ] = fmp_key_word (enckey , j );
1354
+ prd -> file_twkey [j ] = fmp_key_word (twkey , j );
1355
+ }
1356
+
1357
+ /* Increment the data unit number. */
1358
+ dun_lo ++ ;
1359
+ if (dun_lo == 0 )
1360
+ dun_hi ++ ;
1361
+ }
1362
+ return 0 ;
1363
+ }
1364
+
1365
+ #else /* CONFIG_SCSI_UFS_CRYPTO */
1366
+
1367
+ static void exynos_ufs_fmp_init (struct ufs_hba * hba , struct exynos_ufs * ufs )
1368
+ {
1369
+ }
1370
+
1371
+ static void exynos_ufs_fmp_resume (struct ufs_hba * hba )
1372
+ {
1373
+ }
1374
+
1375
+ #define exynos_ufs_fmp_fill_prdt NULL
1376
+
1377
+ #endif /* !CONFIG_SCSI_UFS_CRYPTO */
1378
+
1154
1379
static int exynos_ufs_init (struct ufs_hba * hba )
1155
1380
{
1156
1381
struct device * dev = hba -> dev ;
@@ -1198,6 +1423,8 @@ static int exynos_ufs_init(struct ufs_hba *hba)
1198
1423
1199
1424
exynos_ufs_priv_init (hba , ufs );
1200
1425
1426
+ exynos_ufs_fmp_init (hba , ufs );
1427
+
1201
1428
if (ufs -> drv_data -> drv_init ) {
1202
1429
ret = ufs -> drv_data -> drv_init (dev , ufs );
1203
1430
if (ret ) {
@@ -1213,7 +1440,7 @@ static int exynos_ufs_init(struct ufs_hba *hba)
1213
1440
if (!(ufs -> opts & EXYNOS_UFS_OPT_UFSPR_SECURE ))
1214
1441
exynos_ufs_config_smu (ufs );
1215
1442
1216
- hba -> host -> dma_alignment = SZ_4K - 1 ;
1443
+ hba -> host -> dma_alignment = DATA_UNIT_SIZE - 1 ;
1217
1444
return 0 ;
1218
1445
1219
1446
out :
@@ -1332,7 +1559,7 @@ static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba,
1332
1559
* (ufshcd_async_scan()). Note: this callback may also be called
1333
1560
* from other functions than ufshcd_init().
1334
1561
*/
1335
- hba -> host -> max_segment_size = SZ_4K ;
1562
+ hba -> host -> max_segment_size = DATA_UNIT_SIZE ;
1336
1563
1337
1564
if (ufs -> drv_data -> pre_hce_enable ) {
1338
1565
ret = ufs -> drv_data -> pre_hce_enable (ufs );
@@ -1432,7 +1659,7 @@ static int exynos_ufs_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
1432
1659
phy_power_on (ufs -> phy );
1433
1660
1434
1661
exynos_ufs_config_smu (ufs );
1435
-
1662
+ exynos_ufs_fmp_resume ( hba );
1436
1663
return 0 ;
1437
1664
}
1438
1665
@@ -1698,6 +1925,7 @@ static const struct ufs_hba_variant_ops ufs_hba_exynos_ops = {
1698
1925
.hibern8_notify = exynos_ufs_hibern8_notify ,
1699
1926
.suspend = exynos_ufs_suspend ,
1700
1927
.resume = exynos_ufs_resume ,
1928
+ .fill_crypto_prdt = exynos_ufs_fmp_fill_prdt ,
1701
1929
};
1702
1930
1703
1931
static struct ufs_hba_variant_ops ufs_hba_exynosauto_vh_ops = {
0 commit comments