blob: 211247210ae0d37230e6ebcf135c7ed0fc2ac5b5 [file] [log] [blame]
/*
* Copyright (C) 2016 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _EXYNOS_FMP_H_
#define _EXYNOS_FMP_H_
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#define FMP_KEY_SIZE_16 16
#define FMP_KEY_SIZE_32 32
#define FMP_IV_SIZE_16 16
#define FMP_CBC_MAX_KEY_SIZE FMP_KEY_SIZE_16
#define FMP_XTS_MAX_KEY_SIZE ((FMP_KEY_SIZE_32) * (2))
#define FMP_MAX_KEY_SIZE FMP_XTS_MAX_KEY_SIZE
#define FMP_HOST_TYPE_NAME_LEN 8
#define FMP_BLOCK_TYPE_NAME_LEN 8
#define FMP_SECTOR_SIZE 0x1000
#define FMP_MIN_SECTOR_SIZE 0x200
#define NUM_SECTOR_UNIT ((FMP_SECTOR_SIZE)/(FMP_MIN_SECTOR_SIZE))
#define MAX_AES_XTS_TRANSFER_SIZE 0x1000
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#if defined(CONFIG_MMC_DW_EXYNOS_FMP)
#define TRANS_DESC_LEN_MULTIPLIER 4
#else
#define TRANS_DESC_LEN_MULTIPLIER 1
#endif
enum fmp_id {
FMP_EMBEDDED = 0,
FMP_UFSCARD = 1,
FMP_SDCARD = 2,
};
enum fmp_crypto_algo_mode {
EXYNOS_FMP_BYPASS_MODE = 0,
EXYNOS_FMP_ALGO_MODE_AES_CBC = 1,
EXYNOS_FMP_ALGO_MODE_AES_XTS = 2,
};
enum fmp_crypto_key_size {
EXYNOS_FMP_KEY_SIZE_16 = 16,
EXYNOS_FMP_KEY_SIZE_32 = 32,
};
enum fmp_crypto_enc_mode {
EXYNOS_FMP_DISK_ENC = 1,
EXYNOS_FMP_FILE_ENC = 2,
};
enum fmp_disk_key_status {
KEY_STORED = 0,
KEY_SET = 1,
KEY_CLEAR = 2,
KEY_ERROR = -1,
};
struct fmp_crypto_setting {
enum fmp_crypto_algo_mode algo_mode;
enum fmp_crypto_enc_mode enc_mode;
enum fmp_crypto_key_size key_size;
uint32_t index;
sector_t sector;
unsigned char key[FMP_MAX_KEY_SIZE];
uint8_t iv[FMP_IV_SIZE_16];
};
struct fmp_table_setting {
__le32 des0;
#define GET_CMDQ_LENGTH(d) \
(((d)->des0 & 0xffff0000) >> 16)
__le32 des1;
__le32 des2;
/* Legacy Operation */
#define FKL BIT(26)
#define DKL BIT(27)
#define SET_FAS(d, v) \
((d)->des2 = ((d)->des2 & 0xcfffffff) | v << 28)
#define SET_DAS(d, v) \
((d)->des2 = ((d)->des2 & 0x3fffffff) | v << 30)
#define GET_FAS(d) ((d)->des2 & 0x30000000)
#define GET_DAS(d) ((d)->des2 & 0xc0000000)
#define GET_LENGTH(d) \
((d)->des2 & 0x3ffffff)
__le32 des3;
/* CMDQ Operation */
#define FKL_CMDQ BIT(0)
#define DKL_CMDQ BIT(1)
#define SET_CMDQ_FAS(d, v) \
((d)->des3 = ((d)->des3 & 0xfffffff3) | v << 2)
#define SET_CMDQ_DAS(d, v) \
((d)->des3 = ((d)->des3 & 0xffffffcf) | v << 4)
#define GET_CMDQ_FAS(d) ((d)->des3 & 0x0000000c)
#define GET_CMDQ_DAS(d) ((d)->des3 & 0x00000030)
__le32 des4;
__le32 des5;
__le32 des6;
__le32 des7;
__le32 file_iv0;
__le32 file_iv1;
__le32 file_iv2;
__le32 file_iv3;
__le32 file_enckey0;
__le32 file_enckey1;
__le32 file_enckey2;
__le32 file_enckey3;
__le32 file_enckey4;
__le32 file_enckey5;
__le32 file_enckey6;
__le32 file_enckey7;
__le32 file_twkey0;
__le32 file_twkey1;
__le32 file_twkey2;
__le32 file_twkey3;
__le32 file_twkey4;
__le32 file_twkey5;
__le32 file_twkey6;
__le32 file_twkey7;
__le32 disk_iv0;
__le32 disk_iv1;
__le32 disk_iv2;
__le32 disk_iv3;
};
struct fmp_data_setting {
struct fmp_crypto_setting disk;
struct fmp_crypto_setting file;
struct fmp_table_setting *table;
struct address_space *mapping;
bool cmdq_enabled;
};
struct exynos_fmp_variant_ops {
const char *name;
int (*config)(struct platform_device *, struct fmp_data_setting *);
int (*set_disk_key)(struct platform_device *, struct fmp_data_setting *);
int (*clear_disk_key)(struct platform_device *);
int (*clear)(struct platform_device *, struct fmp_data_setting *);
};
struct fmp_fips_data {
char block_type[FMP_BLOCK_TYPE_NAME_LEN];
struct block_device *bdev;
sector_t sector;
dev_t devt;
struct fmp_crypto_setting *crypto;
uint32_t test_block_offset;
};
struct exynos_fmp {
struct list_head list;
int id;
int command;
struct device *dev;
char host_type[FMP_HOST_TYPE_NAME_LEN];
struct miscdevice miscdev;
struct fmp_fips_data *fips_data;
struct platform_device *host_pdev;
int test_mode;
struct buffer_head *test_bh;
bool fips_result;
int status_disk_key;
};
struct exynos_fmp_variant_ops *exynos_fmp_get_variant_ops(struct device_node *node);
struct platform_device *exynos_fmp_get_pdevice(struct device_node *node);
#endif