kernel_samsung_a53x/drivers/scsi/ufs/ufs-exynos.h
2024-06-15 16:02:09 -03:00

257 lines
5.6 KiB
C
Executable file

/*
* UFS Host Controller driver for Exynos specific extensions
*
* Copyright (C) 2013-2014 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 _UFS_EXYNOS_H_
#define _UFS_EXYNOS_H_
#if IS_ENABLED(CONFIG_EXYNOS_PM_QOS)
#include <soc/samsung/exynos_pm_qos.h>
#endif
#include <linux/platform_device.h>
#define UFS_VER_0004 4
#define UFS_VER_0005 5
#define EOM_DEF_VREF_MAX 256
#define RV_SUCCESS 0
#define H8T_GRANULARITY 100
#define BIT_POS_DBG_DL_RX_INFO_FORCE 28
#define BIT_POS_DBG_DL_RX_INFO_TYPE 18
#define DL_RX_INFO_TYPE_ERROR_DETECTED 21
enum {
UFS_S_MON_LV1 = (1 << 0),
UFS_S_MON_LV2 = (1 << 1),
};
struct ext_cxt {
u32 offset;
u32 mask;
u32 val;
};
/*
* H_UTP_BOOST and H_FATAL_ERR arn't in here because they were just
* defined to enable some callback functions explanation.
*/
enum exynos_host_state {
H_DISABLED = 0,
H_RESET = 1,
H_LINK_UP = 2,
H_LINK_BOOST = 3,
H_TM_BUSY = 4,
H_REQ_BUSY = 5,
H_HIBERN8 = 6,
H_SUSPEND = 7,
};
enum exynos_clk_state {
C_OFF = 0,
C_ON,
};
enum exynos_ufs_ext_blks {
EXT_SYSREG = 0,
EXT_BLK_MAX,
#define EXT_BLK_MAX 1
};
enum exynos_ufs_param_id {
UFS_S_PARAM_EOM_VER = 0,
UFS_S_PARAM_EOM_SZ,
UFS_S_PARAM_EOM_OFS,
UFS_S_PARAM_LANE,
UFS_S_PARAM_H8_D_MS,
UFS_S_PARAM_MON,
UFS_S_PARAM_NUM,
};
enum exynos_ufs_ah8_state {
UFS_STATE_AH8,
UFS_STATE_IDLE,
};
/* UFSHCD states */
enum {
UFSHCD_STATE_RESET,
UFSHCD_STATE_ERROR,
UFSHCD_STATE_OPERATIONAL,
UFSHCD_STATE_EH_SCHEDULED_FATAL,
UFSHCD_STATE_EH_SCHEDULED_NON_FATAL,
};
struct exynos_ufs {
struct device *dev;
struct ufs_hba *hba;
/*
* Do not change the order of iomem variables.
* Standard HCI regision is populated in core driver.
*/
void __iomem *reg_hci; /* exynos-specific hci */
void __iomem *reg_unipro; /* unipro */
void __iomem *reg_ufsp; /* ufs protector */
void __iomem *reg_phy; /* phy */
void __iomem *reg_cport; /* cport */
#define NUM_OF_UFS_MMIO_REGIONS 5
/*
* Do not change the order of remap variables.
*/
struct regmap *regmap_sys; /* io coherency */
struct ext_cxt cxt_phy_iso;
struct ext_cxt cxt_iocc;
/*
* Do not change the order of clock variables
*/
struct clk *clk_hci;
struct clk *clk_unipro;
/* exynos specific state */
enum exynos_host_state h_state;
enum exynos_host_state h_state_prev;
enum exynos_clk_state c_state;
u32 mclk_rate;
int num_rx_lanes;
int num_tx_lanes;
struct uic_pwr_mode req_pmd_parm;
struct uic_pwr_mode act_pmd_parm;
int id;
/* Support system power mode */
int idle_ip_index;
/* PM QoS for stability, not for performance */
#if IS_ENABLED(CONFIG_EXYNOS_PM_QOS)
struct exynos_pm_qos_request pm_qos_int;
#endif
s32 pm_qos_int_value;
/* cal */
struct ufs_cal_param cal_param;
/* performance */
void *perf;
struct ufs_vs_handle handle;
u32 peer_available_lane_rx;
u32 peer_available_lane_tx;
u32 available_lane_rx;
u32 available_lane_tx;
/*
* This variable is to make UFS driver's operations change
* for specific purposes, e.g. unit test cases, or report
* some information to user land.
*/
u32 params[UFS_S_PARAM_NUM];
/* sysfs */
struct kobject sysfs_kobj;
/* async resume */
struct work_struct resume_work;
u32 ah8_ahit;
u32 hibern8_state;
u32 hibern8_enter_cnt;
u32 hibern8_exit_cnt;
/* value 1 whenever resuming, and then we can deal with
UAC(Unit Attention Condition). */
u32 resume_state;
bool suspend_done;
/* This variable is for featuring hw functionality */
void *fmp;
/* flag for runtime */
unsigned long flag;
#define EXYNOS_UFS_BIT_DBG_DUMP (0)
#define EXYNOS_UFS_BIT_CHK_NEXUS (1)
/* cache of hardware contents */
unsigned long nexus;
bool skip_flush;
bool deep_suspended;
};
static inline struct exynos_ufs *to_exynos_ufs(struct ufs_hba *hba)
{
return dev_get_platdata(hba->dev);
}
static inline u32 __get_upmcrs(struct exynos_ufs *ufs)
{
return (std_readl(&ufs->handle, REG_CONTROLLER_STATUS) >> 8) & 0x7;
}
int exynos_ufs_init_dbg(struct ufs_vs_handle *);
int exynos_ufs_dbg_set_lanes(struct ufs_vs_handle *,
struct device *dev, u32);
void exynos_ufs_dump_info(struct ufs_hba *, struct ufs_vs_handle *,
struct device *dev);
void exynos_ufs_cmd_log_start(struct ufs_vs_handle *,
struct ufs_hba *, struct scsi_cmnd *);
void exynos_ufs_cmd_log_end(struct ufs_vs_handle *,
struct ufs_hba *hba, int tag);
#ifdef CONFIG_SCSI_UFS_EXYNOS_FMP
void exynos_ufs_fmp_init(struct ufs_hba *hba);
void exynos_ufs_fmp_resume(struct ufs_hba *hba);
void exynos_ufs_fmp_dump_info(struct ufs_hba *hba);
#ifdef CONFIG_KEYS_IN_PRDT
static inline void exynos_ufs_fmp_set_crypto_cfg(struct ufs_hba *hba)
{
}
#else
void exynos_ufs_fmp_set_crypto_cfg(struct ufs_hba *hba);
#endif
#else /* !CONFIG_SCSI_UFS_EXYNOS_FMP */
static inline void exynos_ufs_fmp_init(struct ufs_hba *hba)
{
}
static inline void exynos_ufs_fmp_resume(struct ufs_hba *hba)
{
}
static inline void exynos_ufs_fmp_dump_info(struct ufs_hba *hba)
{
}
static inline void exynos_ufs_fmp_set_crypto_cfg(struct ufs_hba *hba)
{
}
#endif /* ONFIG_SCSI_UFS_EXYNOS_FMP */
#if IS_ENABLED(CONFIG_SCSI_UFS_EXYNOS_SRPMB)
int exynos_ufs_srpmb_config(struct ufs_hba *hba);
struct scsi_device *exynos_ufs_srpmb_sdev(void);
#else
static inline int exynos_ufs_srpmb_config(struct ufs_hba *hba)
{
return -1;
}
static inline struct scsi_device *exynos_ufs_srpmb_sdev(void)
{
return NULL;
}
#endif
int exynos_ufs_init_mem_log(struct platform_device *pdev);
int ufs_call_cal(struct exynos_ufs *ufs, int init, void *func);
#endif /* _UFS_EXYNOS_H_ */