linux/drivers/ufs/host/ufs-exynos.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * UFS Host Controller driver for Exynos specific extensions
 *
 * Copyright (C) 2014-2015 Samsung Electronics Co., Ltd.
 * Author: Seungwon Jeon  <[email protected]>
 * Author: Alim Akhtar <[email protected]>
 *
 */

#include <asm/unaligned.h>
#include <crypto/aes.h>
#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

#include <ufs/ufshcd.h>
#include "ufshcd-pltfrm.h"
#include <ufs/ufshci.h>
#include <ufs/unipro.h>

#include "ufs-exynos.h"

#define DATA_UNIT_SIZE

/*
 * Exynos's Vendor specific registers for UFSHCI
 */
#define HCI_TXPRDT_ENTRY_SIZE
#define PRDT_PREFECT_EN
#define HCI_RXPRDT_ENTRY_SIZE
#define HCI_1US_TO_CNT_VAL
#define CNT_VAL_1US_MASK
#define HCI_UTRL_NEXUS_TYPE
#define HCI_UTMRL_NEXUS_TYPE
#define HCI_SW_RST
#define UFS_LINK_SW_RST
#define UFS_UNIPRO_SW_RST
#define UFS_SW_RST_MASK
#define HCI_DATA_REORDER
#define HCI_UNIPRO_APB_CLK_CTRL
#define UNIPRO_APB_CLK(v, x)
#define HCI_AXIDMA_RWDATA_BURST_LEN
#define HCI_GPIO_OUT
#define HCI_ERR_EN_PA_LAYER
#define HCI_ERR_EN_DL_LAYER
#define HCI_ERR_EN_N_LAYER
#define HCI_ERR_EN_T_LAYER
#define HCI_ERR_EN_DME_LAYER
#define HCI_V2P1_CTRL
#define IA_TICK_SEL
#define HCI_CLKSTOP_CTRL
#define REFCLKOUT_STOP
#define MPHY_APBCLK_STOP
#define REFCLK_STOP
#define UNIPRO_MCLK_STOP
#define UNIPRO_PCLK_STOP
#define CLK_STOP_MASK
/* HCI_MISC is also known as HCI_FORCE_HCS */
#define HCI_MISC
#define REFCLK_CTRL_EN
#define UNIPRO_PCLK_CTRL_EN
#define UNIPRO_MCLK_CTRL_EN
#define HCI_CORECLK_CTRL_EN
#define CLK_CTRL_EN_MASK
/* Device fatal error */
#define DFES_ERR_EN
#define DFES_DEF_L2_ERRS
#define DFES_DEF_L3_ERRS
#define DFES_DEF_L4_ERRS

/* FSYS UFS Shareability */
#define UFS_WR_SHARABLE
#define UFS_RD_SHARABLE
#define UFS_SHARABLE
#define UFS_SHAREABILITY_OFFSET

/* Multi-host registers */
#define MHCTRL
#define MHCTRL_EN_VH_MASK
#define MHCTRL_EN_VH(vh)
#define PH2VH_MBOX

#define MH_MSG_MASK

#define MH_MSG(id, msg)
#define MH_MSG_PH_READY
#define MH_MSG_VH_READY

#define ALLOW_INQUIRY
#define ALLOW_MODE_SELECT
#define ALLOW_MODE_SENSE
#define ALLOW_PRE_FETCH
#define ALLOW_READ_CMD_ALL
#define ALLOW_READ_BUFFER
#define ALLOW_READ_CAPACITY
#define ALLOW_REPORT_LUNS
#define ALLOW_REQUEST_SENSE
#define ALLOW_SYNCHRONIZE_CACHE
#define ALLOW_TEST_UNIT_READY
#define ALLOW_UNMAP
#define ALLOW_VERIFY
#define ALLOW_WRITE_CMD_ALL

#define ALLOW_TRANS_VH_DEFAULT

#define HCI_MH_ALLOWABLE_TRAN_OF_VH
#define HCI_MH_IID_IN_TASK_TAG

#define PH_READY_TIMEOUT_MS

enum {};

/*
 * UNIPRO registers
 */
#define UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER0
#define UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER1
#define UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER2
#define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER0
#define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER1
#define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER2

/*
 * UFS Protector registers
 */
#define UFSPRSECURITY
#define NSSMU
#define UFSPSBEGIN0
#define UFSPSEND0
#define UFSPSLUN0
#define UFSPSCTRL0

#define CNTR_DIV_VAL

static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en);
static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en);

static inline void exynos_ufs_enable_auto_ctrl_hcc(struct exynos_ufs *ufs)
{}

static inline void exynos_ufs_disable_auto_ctrl_hcc(struct exynos_ufs *ufs)
{}

static inline void exynos_ufs_disable_auto_ctrl_hcc_save(
					struct exynos_ufs *ufs, u32 *val)
{}

static inline void exynos_ufs_auto_ctrl_hcc_restore(
					struct exynos_ufs *ufs, u32 *val)
{}

static inline void exynos_ufs_gate_clks(struct exynos_ufs *ufs)
{}

static inline void exynos_ufs_ungate_clks(struct exynos_ufs *ufs)
{}

static int exynos7_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs)
{}

static int exynosauto_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs)
{}

static int exynosauto_ufs_post_hce_enable(struct exynos_ufs *ufs)
{}

static int exynosauto_ufs_pre_link(struct exynos_ufs *ufs)
{}

static int exynosauto_ufs_pre_pwr_change(struct exynos_ufs *ufs,
					 struct ufs_pa_layer_attr *pwr)
{}

static int exynosauto_ufs_post_pwr_change(struct exynos_ufs *ufs,
					  struct ufs_pa_layer_attr *pwr)
{}

static int exynos7_ufs_pre_link(struct exynos_ufs *ufs)
{}

static int exynos7_ufs_post_link(struct exynos_ufs *ufs)
{}

static int exynos7_ufs_pre_pwr_change(struct exynos_ufs *ufs,
						struct ufs_pa_layer_attr *pwr)
{}

static int exynos7_ufs_post_pwr_change(struct exynos_ufs *ufs,
						struct ufs_pa_layer_attr *pwr)
{}

/*
 * exynos_ufs_auto_ctrl_hcc - HCI core clock control by h/w
 * Control should be disabled in the below cases
 * - Before host controller S/W reset
 * - Access to UFS protector's register
 */
static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en)
{}

static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en)
{}

static int exynos_ufs_get_clk_info(struct exynos_ufs *ufs)
{}

static void exynos_ufs_set_unipro_pclk_div(struct exynos_ufs *ufs)
{}

static void exynos_ufs_set_pwm_clk_div(struct exynos_ufs *ufs)
{}

static void exynos_ufs_calc_pwm_clk_div(struct exynos_ufs *ufs)
{}

long exynos_ufs_calc_time_cntr(struct exynos_ufs *ufs, long period)
{}

static void exynos_ufs_specify_phy_time_attr(struct exynos_ufs *ufs)
{}

static void exynos_ufs_config_phy_time_attr(struct exynos_ufs *ufs)
{}

static void exynos_ufs_config_phy_cap_attr(struct exynos_ufs *ufs)
{}

static void exynos_ufs_establish_connt(struct exynos_ufs *ufs)
{}

static void exynos_ufs_config_smu(struct exynos_ufs *ufs)
{}

static void exynos_ufs_config_sync_pattern_mask(struct exynos_ufs *ufs,
					struct ufs_pa_layer_attr *pwr)
{}

static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba,
				struct ufs_pa_layer_attr *dev_max_params,
				struct ufs_pa_layer_attr *dev_req_params)
{}

#define PWR_MODE_STR_LEN
static int exynos_ufs_post_pwr_mode(struct ufs_hba *hba,
				struct ufs_pa_layer_attr *pwr_req)
{}

static void exynos_ufs_specify_nexus_t_xfer_req(struct ufs_hba *hba,
						int tag, bool is_scsi_cmd)
{}

static void exynos_ufs_specify_nexus_t_tm_req(struct ufs_hba *hba,
						int tag, u8 func)
{}

static int exynos_ufs_phy_init(struct exynos_ufs *ufs)
{}

static void exynos_ufs_config_unipro(struct exynos_ufs *ufs)
{}

static void exynos_ufs_config_intr(struct exynos_ufs *ufs, u32 errs, u8 index)
{}

static int exynos_ufs_setup_clocks(struct ufs_hba *hba, bool on,
				   enum ufs_notify_change_status status)
{}

static int exynos_ufs_pre_link(struct ufs_hba *hba)
{}

static void exynos_ufs_fit_aggr_timeout(struct exynos_ufs *ufs)
{}

static int exynos_ufs_post_link(struct ufs_hba *hba)
{}

static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs)
{}

static inline void exynos_ufs_priv_init(struct ufs_hba *hba,
					struct exynos_ufs *ufs)
{}

#ifdef CONFIG_SCSI_UFS_CRYPTO

/*
 * Support for Flash Memory Protector (FMP), which is the inline encryption
 * hardware on Exynos and Exynos-based SoCs.  The interface to this hardware is
 * not compatible with the standard UFS crypto.  It requires that encryption be
 * configured in the PRDT using a nonstandard extension.
 */

enum fmp_crypto_algo_mode {};
enum fmp_crypto_key_length {};

/**
 * struct fmp_sg_entry - nonstandard format of PRDT entries when FMP is enabled
 *
 * @base: The standard PRDT entry, but with nonstandard bitfields in the high
 *	bits of the 'size' field, i.e. the last 32-bit word.  When these
 *	nonstandard bitfields are zero, the data segment won't be encrypted or
 *	decrypted.  Otherwise they specify the algorithm and key length with
 *	which the data segment will be encrypted or decrypted.
 * @file_iv: The initialization vector (IV) with all bytes reversed
 * @file_enckey: The first half of the AES-XTS key with all bytes reserved
 * @file_twkey: The second half of the AES-XTS key with all bytes reserved
 * @disk_iv: Unused
 * @reserved: Unused
 */
struct fmp_sg_entry {};

#define SMC_CMD_FMP_SECURITY
#define SMC_CMD_SMU
#define SMC_CMD_FMP_SMU_RESUME
#define SMU_EMBEDDED
#define SMU_INIT
#define CFG_DESCTYPE_3

static void exynos_ufs_fmp_init(struct ufs_hba *hba, struct exynos_ufs *ufs)
{}

static void exynos_ufs_fmp_resume(struct ufs_hba *hba)
{}

static inline __be64 fmp_key_word(const u8 *key, int j)
{}

/* Fill the PRDT for a request according to the given encryption context. */
static int exynos_ufs_fmp_fill_prdt(struct ufs_hba *hba,
				    const struct bio_crypt_ctx *crypt_ctx,
				    void *prdt, unsigned int num_segments)
{}

#else /* CONFIG_SCSI_UFS_CRYPTO */

static void exynos_ufs_fmp_init(struct ufs_hba *hba, struct exynos_ufs *ufs)
{
}

static void exynos_ufs_fmp_resume(struct ufs_hba *hba)
{
}

#define exynos_ufs_fmp_fill_prdt

#endif /* !CONFIG_SCSI_UFS_CRYPTO */

static int exynos_ufs_init(struct ufs_hba *hba)
{}

static int exynos_ufs_host_reset(struct ufs_hba *hba)
{}

static void exynos_ufs_dev_hw_reset(struct ufs_hba *hba)
{}

static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter)
{}

static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter)
{}

static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba,
					enum ufs_notify_change_status status)
{}

static int exynos_ufs_link_startup_notify(struct ufs_hba *hba,
					  enum ufs_notify_change_status status)
{}

static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba,
				enum ufs_notify_change_status status,
				struct ufs_pa_layer_attr *dev_max_params,
				struct ufs_pa_layer_attr *dev_req_params)
{}

static void exynos_ufs_hibern8_notify(struct ufs_hba *hba,
				     enum uic_cmd_dme enter,
				     enum ufs_notify_change_status notify)
{}

static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
	enum ufs_notify_change_status status)
{}

static int exynos_ufs_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
{}

static int exynosauto_ufs_vh_link_startup_notify(struct ufs_hba *hba,
						 enum ufs_notify_change_status status)
{}

static int exynosauto_ufs_vh_wait_ph_ready(struct ufs_hba *hba)
{}

static int exynosauto_ufs_vh_init(struct ufs_hba *hba)
{}

static int fsd_ufs_pre_link(struct exynos_ufs *ufs)
{}

static int fsd_ufs_post_link(struct exynos_ufs *ufs)
{}

static int fsd_ufs_pre_pwr_change(struct exynos_ufs *ufs,
					struct ufs_pa_layer_attr *pwr)
{}

static inline u32 get_mclk_period_unipro_18(struct exynos_ufs *ufs)
{}

static int gs101_ufs_pre_link(struct exynos_ufs *ufs)
{}

static int gs101_ufs_post_link(struct exynos_ufs *ufs)
{}

static int gs101_ufs_pre_pwr_change(struct exynos_ufs *ufs,
					 struct ufs_pa_layer_attr *pwr)
{}

static const struct ufs_hba_variant_ops ufs_hba_exynos_ops =;

static struct ufs_hba_variant_ops ufs_hba_exynosauto_vh_ops =;

static int exynos_ufs_probe(struct platform_device *pdev)
{}

static void exynos_ufs_remove(struct platform_device *pdev)
{}

static struct exynos_ufs_uic_attr exynos7_uic_attr =;

static const struct exynos_ufs_drv_data exynosauto_ufs_drvs =;

static const struct exynos_ufs_drv_data exynosauto_ufs_vh_drvs =;

static const struct exynos_ufs_drv_data exynos_ufs_drvs =;

static struct exynos_ufs_uic_attr gs101_uic_attr =;

static struct exynos_ufs_uic_attr fsd_uic_attr =;

static const struct exynos_ufs_drv_data fsd_ufs_drvs =;

static const struct exynos_ufs_drv_data gs101_ufs_drvs =;

static const struct of_device_id exynos_ufs_of_match[] =;
MODULE_DEVICE_TABLE(of, exynos_ufs_of_match);

static const struct dev_pm_ops exynos_ufs_pm_ops =;

static struct platform_driver exynos_ufs_pltform =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();