blob: 973df8c18cfdc1efaace3b54d3327d2acc9ca720 [file] [log] [blame]
/*
* Copyright (C) 2018 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*/
#ifndef _UFS_MTK_H
#define _UFS_MTK_H
#define CONFIG_MTK_UFS_DEBUG
/* #define CONFIG_MTK_UFS_DEGUG_GPIO_TRIGGER */
#ifdef CONFIG_MTK_ENG_BUILD
#define CONFIG_MTK_UFS_LBA_CRC16_CHECK
#endif
#include <linux/of.h>
#include <linux/rpmb.h>
#include <linux/pm_qos.h>
#include "ufshcd.h"
#define UPIU_COMMAND_CRYPTO_EN_OFFSET 23
#define UFS_RPMB_DEV_MAX_RW_SIZE_LIMITATION (8)
struct ufs_crypto_map {
unsigned char flag;
unsigned char key;
};
#define UFS_MAX_LBA ((64 * 1024 * 1024) / 4)
#define UFS_CRYPTO_FLAG_READ (0x01)
#define UFS_CRYPTO_FLAG_WRITE (0x02)
#define UFS_CRYPTO_FLAG_UNMAP (0x04)
#define UFS_CRYPTO_FLAG_NON_ENCRYPTED (0x10)
#define UFS_CRYPTO_FLAG_ENCRYPTED (0x20)
#define UFS_CRYPTO_FLAG_VALID (UFS_CRYPTO_FLAG_ENCRYPTED | \
UFS_CRYPTO_FLAG_NON_ENCRYPTED)
#define UFS_HIE_PARAM_OFS_CFG_ID (24)
#define UFS_HIE_PARAM_OFS_MODE (16)
#define UFS_HIE_PARAM_OFS_KEY_TOTAL_BYTE (8)
#define UFS_HIE_PARAM_OFS_KEY_START_BYTE (0)
enum ufs_crypto_type {
UFS_CRYPTO_NON_ENCRYPTED,
UFS_CRYPTO_ENCRYPT,
UFS_CRYPTO_DECRYPT,
};
enum ufs_trace_event {
UFS_TRACE_SEND,
UFS_TRACE_COMPLETED,
UFS_TRACE_DEV_SEND,
UFS_TRACE_DEV_COMPLETED,
UFS_TRACE_TM_SEND,
UFS_TRACE_TM_COMPLETED,
UFS_TRACE_UIC_SEND,
UFS_TRACE_UIC_CMPL_GENERAL,
UFS_TRACE_UIC_CMPL_PWR_CTRL,
UFS_TRACE_REG_TOGGLE,
UFS_TRACE_ABORTING,
UFS_TRACE_DI_FAIL,
UFS_TRACE_DEVICE_RESET,
UFS_TRACE_PERF_MODE,
UFS_TRACE_DEBUG_PROC,
UFS_TRACE_GENERIC,
};
enum {
UNIPRO_CG_CFG_NATURE = 0, /* not force */
UNIPRO_CG_CFG_FORCE_ENABLE = 1,
UNIPRO_CG_CFG_FORCE_DISABLE = 2,
};
enum {
UFS_CRYPTO_ALGO_AES_XTS = 0,
UFS_CRYPTO_ALGO_BITLOCKER_AES_CBC = 1,
UFS_CRYPTO_ALGO_AES_ECB = 2,
UFS_CRYPTO_ALGO_ESSIV_AES_CBC = 3,
};
enum {
UFS_H8 = 0x0,
UFS_H8_SUSPEND = 0x1,
};
#define H8_POLL_TOUT_MS 100
enum perf_mode {
PERF_FORCE_DISABLE = 0,
PERF_FORCE_ENABLE = 1,
PERF_AUTO = 2,
};
struct ufs_cmd_str_struct {
char str[32];
char cmd;
};
#ifdef MTK_UFS_HQA
#define UFS_CACHED_REGION_CNT (3)
#else
#define UFS_CACHED_REGION_CNT (2)
#endif
struct ufs_cached_region {
char *name;
sector_t start_sect;
sector_t end_sect;
};
/*
* Hynix device need max 3 seconds to clear fDeviceInit,
* each fDeviceInit transaction takes
* around 1~2ms to get response from UFS.
* Max fDeviceInit clear time = 5000*(1~2)ms > 3seconds
*/
#define UFS_FDEVICEINIT_RETRIES (5000)
#define UFS_DESCRIPTOR_SIZE (255)
struct ufs_descriptor {
u8 descriptor_idn;
u8 index;
u8 descriptor[UFS_DESCRIPTOR_SIZE];
u8 *qresp_upiu;
u32 qresp_upiu_size;
};
union ufs_cpt_cap {
u32 cap_raw;
struct {
u8 cap_cnt;
u8 cfg_cnt;
u8 resv;
u8 cfg_ptr;
} cap;
};
union ufs_cpt_capx {
u32 capx_raw;
struct {
u8 alg_id;
u8 du_size;
u8 key_size;
u8 resv;
} capx;
};
union ufs_cap_cfg {
u32 cfgx_raw[32];
struct {
u32 key[16];
u8 du_size;
u8 cap_id;
u16 resv0 : 15;
u16 cfg_en : 1;
u8 mu1ti_host;
u8 resv1;
u16 vsb;
u32 resv2[14];
} cfgx;
};
struct ufs_crypto {
u32 cfg_id;
u32 cap_id;
union ufs_cpt_cap cap;
union ufs_cpt_capx capx;
union ufs_cap_cfg cfg;
};
struct ufs_crypt_info {
struct ufs_hba *hba;
struct scsi_cmnd *cmd;
};
struct ufs_mtk_host {
struct ufs_hba *hba;
/* performance mode */
enum perf_mode perf_mode;
bool perf_en;
bool spm_sw_mode;
bool unipro_lpm;
bool vreg_lpm_supported;
int crypto_vcore_opp;
struct clk *crypto_clk_mux;
struct clk *crypto_parent_clk_normal;
struct clk *crypto_parent_clk_perf;
bool pm_qos_init;
struct pm_qos_request *req_vcore;
struct pm_qos_request req_cpu_dma_latency;
/* passthrough keyhint if number of key slots is enough */
bool passthrough_keyhint;
};
enum {
PMQOS_UNREQ = 0,
PMQOS_REQ = 1,
PMQOS_UNREQING = 2,
PMQOS_REQING = 3
};
extern bool ufs_mtk_auto_hibern8_enabled;
extern enum ufs_dbg_lvl_t ufs_mtk_dbg_lvl;
extern struct ufs_hba *ufs_mtk_hba;
extern bool ufs_mtk_host_deep_stall_enable;
extern bool ufs_mtk_host_scramble_enable;
void ufs_mtk_add_sysfs_nodes(struct ufs_hba *hba);
int ufs_mtk_auto_hiber8_quirk_handler(struct ufs_hba *hba, bool enable);
void ufs_mtk_cache_setup_cmd(struct scsi_cmnd *cmd);
void ufs_mtk_crypto_cal_dun(u32 alg_id, u64 iv, u32 *dunl, u32 *dunu);
void ufs_mtk_dbg_dump_scsi_cmd(struct ufs_hba *hba,
struct scsi_cmnd *cmd, u32 flag);
int ufs_mtk_deepidle_hibern8_check(void);
void ufs_mtk_deepidle_leave(void);
int ufs_mtk_generic_read_dme_no_check(u32 uic_cmd, u16 mib_attribute,
u16 gen_select_index, u32 *value, unsigned long retry_ms);
int ufs_mtk_generic_read_dme(u32 uic_cmd, u16 mib_attribute,
u16 gen_select_index, u32 *value, unsigned long retry_ms);
void ufs_mtk_hwfde_cfg_cmd(struct ufs_hba *hba,
struct scsi_cmnd *cmd);
int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 *state,
unsigned long retry_ms);
int ufs_mtk_linkup_fail_handler(struct ufs_hba *hba, int left_retry);
void ufs_mtk_parse_auto_hibern8_timer(struct ufs_hba *hba);
void ufs_mtk_parse_dt(struct ufs_hba *hba);
bool ufs_mtk_perf_is_supported(struct ufs_mtk_host *host);
int ufs_mtk_perf_setup_crypto_clk(struct ufs_mtk_host *host, bool perf);
int ufs_mtk_perf_setup(struct ufs_mtk_host *host, bool perf);
int ufs_mtk_ioctl_ffu(struct scsi_device *dev, void __user *buf_user);
int ufs_mtk_ioctl_get_fw_ver(struct scsi_device *dev, void __user *buf_user);
int ufs_mtk_ioctl_query(struct ufs_hba *hba, u8 lun, void __user *buf_user);
int ufs_mtk_ioctl_rpmb(struct ufs_hba *hba, void __user *buf_user);
bool ufs_mtk_is_data_write_cmd(char cmd_op);
void ufs_mtk_rpmb_dump_frame(struct scsi_device *sdev, u8 *data_frame, u32 cnt);
struct rpmb_dev *ufs_mtk_rpmb_get_raw_dev(void);
void ufs_mtk_runtime_pm_init(struct scsi_device *sdev);
void ufs_mtk_device_quiesce(struct ufs_hba *hba);
void ufs_mtk_device_resume(struct ufs_hba *hba);
#ifdef CONFIG_MTK_UFS_LBA_CRC16_CHECK
void ufs_mtk_di_init(struct ufs_hba *hba);
int ufs_mtk_di_inspect(struct ufs_hba *hba, struct scsi_cmnd *cmd);
#endif
#if defined(CONFIG_MTK_GIC_EXT)
/* Use in ufshcd_intr() to dump gic status */
extern void mt_irq_dump_status(int irq);
#endif
#endif /* !_UFS_MTK_H */