18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Universal Flash Storage Host controller driver
48c2ecf20Sopenharmony_ci * Copyright (C) 2011-2013 Samsung India Software Operations
58c2ecf20Sopenharmony_ci * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Authors:
88c2ecf20Sopenharmony_ci *	Santosh Yaraganavi <santosh.sy@samsung.com>
98c2ecf20Sopenharmony_ci *	Vinayak Holikatti <h.vinayak@samsung.com>
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#ifndef _UFSHCD_H
138c2ecf20Sopenharmony_ci#define _UFSHCD_H
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <linux/kernel.h>
178c2ecf20Sopenharmony_ci#include <linux/init.h>
188c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
198c2ecf20Sopenharmony_ci#include <linux/io.h>
208c2ecf20Sopenharmony_ci#include <linux/delay.h>
218c2ecf20Sopenharmony_ci#include <linux/slab.h>
228c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
238c2ecf20Sopenharmony_ci#include <linux/rwsem.h>
248c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
258c2ecf20Sopenharmony_ci#include <linux/errno.h>
268c2ecf20Sopenharmony_ci#include <linux/types.h>
278c2ecf20Sopenharmony_ci#include <linux/wait.h>
288c2ecf20Sopenharmony_ci#include <linux/bitops.h>
298c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
308c2ecf20Sopenharmony_ci#include <linux/clk.h>
318c2ecf20Sopenharmony_ci#include <linux/completion.h>
328c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
338c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
348c2ecf20Sopenharmony_ci#include <linux/devfreq.h>
358c2ecf20Sopenharmony_ci#include <linux/keyslot-manager.h>
368c2ecf20Sopenharmony_ci#include "unipro.h"
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#include <asm/irq.h>
398c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
408c2ecf20Sopenharmony_ci#include <scsi/scsi.h>
418c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h>
428c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h>
438c2ecf20Sopenharmony_ci#include <scsi/scsi_tcq.h>
448c2ecf20Sopenharmony_ci#include <scsi/scsi_dbg.h>
458c2ecf20Sopenharmony_ci#include <scsi/scsi_eh.h>
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#include "ufs.h"
488c2ecf20Sopenharmony_ci#include "ufs_quirks.h"
498c2ecf20Sopenharmony_ci#include "ufshci.h"
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define UFSHCD "ufshcd"
528c2ecf20Sopenharmony_ci#define UFSHCD_DRIVER_VERSION "0.2"
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistruct ufs_hba;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cienum dev_cmd_type {
578c2ecf20Sopenharmony_ci	DEV_CMD_TYPE_NOP		= 0x0,
588c2ecf20Sopenharmony_ci	DEV_CMD_TYPE_QUERY		= 0x1,
598c2ecf20Sopenharmony_ci};
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/**
628c2ecf20Sopenharmony_ci * struct uic_command - UIC command structure
638c2ecf20Sopenharmony_ci * @command: UIC command
648c2ecf20Sopenharmony_ci * @argument1: UIC command argument 1
658c2ecf20Sopenharmony_ci * @argument2: UIC command argument 2
668c2ecf20Sopenharmony_ci * @argument3: UIC command argument 3
678c2ecf20Sopenharmony_ci * @cmd_active: Indicate if UIC command is outstanding
688c2ecf20Sopenharmony_ci * @done: UIC command completion
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_cistruct uic_command {
718c2ecf20Sopenharmony_ci	u32 command;
728c2ecf20Sopenharmony_ci	u32 argument1;
738c2ecf20Sopenharmony_ci	u32 argument2;
748c2ecf20Sopenharmony_ci	u32 argument3;
758c2ecf20Sopenharmony_ci	int cmd_active;
768c2ecf20Sopenharmony_ci	struct completion done;
778c2ecf20Sopenharmony_ci};
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/* Used to differentiate the power management options */
808c2ecf20Sopenharmony_cienum ufs_pm_op {
818c2ecf20Sopenharmony_ci	UFS_RUNTIME_PM,
828c2ecf20Sopenharmony_ci	UFS_SYSTEM_PM,
838c2ecf20Sopenharmony_ci	UFS_SHUTDOWN_PM,
848c2ecf20Sopenharmony_ci};
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#define ufshcd_is_runtime_pm(op) ((op) == UFS_RUNTIME_PM)
878c2ecf20Sopenharmony_ci#define ufshcd_is_system_pm(op) ((op) == UFS_SYSTEM_PM)
888c2ecf20Sopenharmony_ci#define ufshcd_is_shutdown_pm(op) ((op) == UFS_SHUTDOWN_PM)
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/* Host <-> Device UniPro Link state */
918c2ecf20Sopenharmony_cienum uic_link_state {
928c2ecf20Sopenharmony_ci	UIC_LINK_OFF_STATE	= 0, /* Link powered down or disabled */
938c2ecf20Sopenharmony_ci	UIC_LINK_ACTIVE_STATE	= 1, /* Link is in Fast/Slow/Sleep state */
948c2ecf20Sopenharmony_ci	UIC_LINK_HIBERN8_STATE	= 2, /* Link is in Hibernate state */
958c2ecf20Sopenharmony_ci	UIC_LINK_BROKEN_STATE	= 3, /* Link is in broken state */
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci#define ufshcd_is_link_off(hba) ((hba)->uic_link_state == UIC_LINK_OFF_STATE)
998c2ecf20Sopenharmony_ci#define ufshcd_is_link_active(hba) ((hba)->uic_link_state == \
1008c2ecf20Sopenharmony_ci				    UIC_LINK_ACTIVE_STATE)
1018c2ecf20Sopenharmony_ci#define ufshcd_is_link_hibern8(hba) ((hba)->uic_link_state == \
1028c2ecf20Sopenharmony_ci				    UIC_LINK_HIBERN8_STATE)
1038c2ecf20Sopenharmony_ci#define ufshcd_is_link_broken(hba) ((hba)->uic_link_state == \
1048c2ecf20Sopenharmony_ci				   UIC_LINK_BROKEN_STATE)
1058c2ecf20Sopenharmony_ci#define ufshcd_set_link_off(hba) ((hba)->uic_link_state = UIC_LINK_OFF_STATE)
1068c2ecf20Sopenharmony_ci#define ufshcd_set_link_active(hba) ((hba)->uic_link_state = \
1078c2ecf20Sopenharmony_ci				    UIC_LINK_ACTIVE_STATE)
1088c2ecf20Sopenharmony_ci#define ufshcd_set_link_hibern8(hba) ((hba)->uic_link_state = \
1098c2ecf20Sopenharmony_ci				    UIC_LINK_HIBERN8_STATE)
1108c2ecf20Sopenharmony_ci#define ufshcd_set_link_broken(hba) ((hba)->uic_link_state = \
1118c2ecf20Sopenharmony_ci				    UIC_LINK_BROKEN_STATE)
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#define ufshcd_set_ufs_dev_active(h) \
1148c2ecf20Sopenharmony_ci	((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE)
1158c2ecf20Sopenharmony_ci#define ufshcd_set_ufs_dev_sleep(h) \
1168c2ecf20Sopenharmony_ci	((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
1178c2ecf20Sopenharmony_ci#define ufshcd_set_ufs_dev_poweroff(h) \
1188c2ecf20Sopenharmony_ci	((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
1198c2ecf20Sopenharmony_ci#define ufshcd_is_ufs_dev_active(h) \
1208c2ecf20Sopenharmony_ci	((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
1218c2ecf20Sopenharmony_ci#define ufshcd_is_ufs_dev_sleep(h) \
1228c2ecf20Sopenharmony_ci	((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
1238c2ecf20Sopenharmony_ci#define ufshcd_is_ufs_dev_poweroff(h) \
1248c2ecf20Sopenharmony_ci	((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci/*
1278c2ecf20Sopenharmony_ci * UFS Power management levels.
1288c2ecf20Sopenharmony_ci * Each level is in increasing order of power savings.
1298c2ecf20Sopenharmony_ci */
1308c2ecf20Sopenharmony_cienum ufs_pm_level {
1318c2ecf20Sopenharmony_ci	UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */
1328c2ecf20Sopenharmony_ci	UFS_PM_LVL_1, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE */
1338c2ecf20Sopenharmony_ci	UFS_PM_LVL_2, /* UFS_SLEEP_PWR_MODE, UIC_LINK_ACTIVE_STATE */
1348c2ecf20Sopenharmony_ci	UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */
1358c2ecf20Sopenharmony_ci	UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */
1368c2ecf20Sopenharmony_ci	UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */
1378c2ecf20Sopenharmony_ci	UFS_PM_LVL_MAX
1388c2ecf20Sopenharmony_ci};
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistruct ufs_pm_lvl_states {
1418c2ecf20Sopenharmony_ci	enum ufs_dev_pwr_mode dev_state;
1428c2ecf20Sopenharmony_ci	enum uic_link_state link_state;
1438c2ecf20Sopenharmony_ci};
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci/**
1468c2ecf20Sopenharmony_ci * struct ufshcd_lrb - local reference block
1478c2ecf20Sopenharmony_ci * @utr_descriptor_ptr: UTRD address of the command
1488c2ecf20Sopenharmony_ci * @ucd_req_ptr: UCD address of the command
1498c2ecf20Sopenharmony_ci * @ucd_rsp_ptr: Response UPIU address for this command
1508c2ecf20Sopenharmony_ci * @ucd_prdt_ptr: PRDT address of the command
1518c2ecf20Sopenharmony_ci * @utrd_dma_addr: UTRD dma address for debug
1528c2ecf20Sopenharmony_ci * @ucd_prdt_dma_addr: PRDT dma address for debug
1538c2ecf20Sopenharmony_ci * @ucd_rsp_dma_addr: UPIU response dma address for debug
1548c2ecf20Sopenharmony_ci * @ucd_req_dma_addr: UPIU request dma address for debug
1558c2ecf20Sopenharmony_ci * @cmd: pointer to SCSI command
1568c2ecf20Sopenharmony_ci * @sense_buffer: pointer to sense buffer address of the SCSI command
1578c2ecf20Sopenharmony_ci * @sense_bufflen: Length of the sense buffer
1588c2ecf20Sopenharmony_ci * @scsi_status: SCSI status of the command
1598c2ecf20Sopenharmony_ci * @command_type: SCSI, UFS, Query.
1608c2ecf20Sopenharmony_ci * @task_tag: Task tag of the command
1618c2ecf20Sopenharmony_ci * @lun: LUN of the command
1628c2ecf20Sopenharmony_ci * @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation)
1638c2ecf20Sopenharmony_ci * @issue_time_stamp: time stamp for debug purposes
1648c2ecf20Sopenharmony_ci * @compl_time_stamp: time stamp for statistics
1658c2ecf20Sopenharmony_ci * @crypto_key_slot: the key slot to use for inline crypto (-1 if none)
1668c2ecf20Sopenharmony_ci * @data_unit_num: the data unit number for the first block for inline crypto
1678c2ecf20Sopenharmony_ci * @req_abort_skip: skip request abort task flag
1688c2ecf20Sopenharmony_ci */
1698c2ecf20Sopenharmony_cistruct ufshcd_lrb {
1708c2ecf20Sopenharmony_ci	struct utp_transfer_req_desc *utr_descriptor_ptr;
1718c2ecf20Sopenharmony_ci	struct utp_upiu_req *ucd_req_ptr;
1728c2ecf20Sopenharmony_ci	struct utp_upiu_rsp *ucd_rsp_ptr;
1738c2ecf20Sopenharmony_ci	struct ufshcd_sg_entry *ucd_prdt_ptr;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	dma_addr_t utrd_dma_addr;
1768c2ecf20Sopenharmony_ci	dma_addr_t ucd_req_dma_addr;
1778c2ecf20Sopenharmony_ci	dma_addr_t ucd_rsp_dma_addr;
1788c2ecf20Sopenharmony_ci	dma_addr_t ucd_prdt_dma_addr;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	struct scsi_cmnd *cmd;
1818c2ecf20Sopenharmony_ci	u8 *sense_buffer;
1828c2ecf20Sopenharmony_ci	unsigned int sense_bufflen;
1838c2ecf20Sopenharmony_ci	int scsi_status;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	int command_type;
1868c2ecf20Sopenharmony_ci	int task_tag;
1878c2ecf20Sopenharmony_ci	u8 lun; /* UPIU LUN id field is only 8-bit wide */
1888c2ecf20Sopenharmony_ci	bool intr_cmd;
1898c2ecf20Sopenharmony_ci	ktime_t issue_time_stamp;
1908c2ecf20Sopenharmony_ci	ktime_t compl_time_stamp;
1918c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_UFS_CRYPTO
1928c2ecf20Sopenharmony_ci	int crypto_key_slot;
1938c2ecf20Sopenharmony_ci	u64 data_unit_num;
1948c2ecf20Sopenharmony_ci#endif
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	bool req_abort_skip;
1978c2ecf20Sopenharmony_ci};
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci/**
2008c2ecf20Sopenharmony_ci * struct ufs_query - holds relevant data structures for query request
2018c2ecf20Sopenharmony_ci * @request: request upiu and function
2028c2ecf20Sopenharmony_ci * @descriptor: buffer for sending/receiving descriptor
2038c2ecf20Sopenharmony_ci * @response: response upiu and response
2048c2ecf20Sopenharmony_ci */
2058c2ecf20Sopenharmony_cistruct ufs_query {
2068c2ecf20Sopenharmony_ci	struct ufs_query_req request;
2078c2ecf20Sopenharmony_ci	u8 *descriptor;
2088c2ecf20Sopenharmony_ci	struct ufs_query_res response;
2098c2ecf20Sopenharmony_ci};
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci/**
2128c2ecf20Sopenharmony_ci * struct ufs_dev_cmd - all assosiated fields with device management commands
2138c2ecf20Sopenharmony_ci * @type: device management command type - Query, NOP OUT
2148c2ecf20Sopenharmony_ci * @lock: lock to allow one command at a time
2158c2ecf20Sopenharmony_ci * @complete: internal commands completion
2168c2ecf20Sopenharmony_ci */
2178c2ecf20Sopenharmony_cistruct ufs_dev_cmd {
2188c2ecf20Sopenharmony_ci	enum dev_cmd_type type;
2198c2ecf20Sopenharmony_ci	struct mutex lock;
2208c2ecf20Sopenharmony_ci	struct completion *complete;
2218c2ecf20Sopenharmony_ci	struct ufs_query query;
2228c2ecf20Sopenharmony_ci};
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci/**
2258c2ecf20Sopenharmony_ci * struct ufs_clk_info - UFS clock related info
2268c2ecf20Sopenharmony_ci * @list: list headed by hba->clk_list_head
2278c2ecf20Sopenharmony_ci * @clk: clock node
2288c2ecf20Sopenharmony_ci * @name: clock name
2298c2ecf20Sopenharmony_ci * @max_freq: maximum frequency supported by the clock
2308c2ecf20Sopenharmony_ci * @min_freq: min frequency that can be used for clock scaling
2318c2ecf20Sopenharmony_ci * @curr_freq: indicates the current frequency that it is set to
2328c2ecf20Sopenharmony_ci * @keep_link_active: indicates that the clk should not be disabled if
2338c2ecf20Sopenharmony_ci		      link is active
2348c2ecf20Sopenharmony_ci * @enabled: variable to check against multiple enable/disable
2358c2ecf20Sopenharmony_ci */
2368c2ecf20Sopenharmony_cistruct ufs_clk_info {
2378c2ecf20Sopenharmony_ci	struct list_head list;
2388c2ecf20Sopenharmony_ci	struct clk *clk;
2398c2ecf20Sopenharmony_ci	const char *name;
2408c2ecf20Sopenharmony_ci	u32 max_freq;
2418c2ecf20Sopenharmony_ci	u32 min_freq;
2428c2ecf20Sopenharmony_ci	u32 curr_freq;
2438c2ecf20Sopenharmony_ci	bool keep_link_active;
2448c2ecf20Sopenharmony_ci	bool enabled;
2458c2ecf20Sopenharmony_ci};
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cienum ufs_notify_change_status {
2488c2ecf20Sopenharmony_ci	PRE_CHANGE,
2498c2ecf20Sopenharmony_ci	POST_CHANGE,
2508c2ecf20Sopenharmony_ci};
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistruct ufs_pa_layer_attr {
2538c2ecf20Sopenharmony_ci	u32 gear_rx;
2548c2ecf20Sopenharmony_ci	u32 gear_tx;
2558c2ecf20Sopenharmony_ci	u32 lane_rx;
2568c2ecf20Sopenharmony_ci	u32 lane_tx;
2578c2ecf20Sopenharmony_ci	u32 pwr_rx;
2588c2ecf20Sopenharmony_ci	u32 pwr_tx;
2598c2ecf20Sopenharmony_ci	u32 hs_rate;
2608c2ecf20Sopenharmony_ci};
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistruct ufs_pwr_mode_info {
2638c2ecf20Sopenharmony_ci	bool is_valid;
2648c2ecf20Sopenharmony_ci	struct ufs_pa_layer_attr info;
2658c2ecf20Sopenharmony_ci};
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci/**
2688c2ecf20Sopenharmony_ci * struct ufs_hba_variant_ops - variant specific callbacks
2698c2ecf20Sopenharmony_ci * @name: variant name
2708c2ecf20Sopenharmony_ci * @init: called when the driver is initialized
2718c2ecf20Sopenharmony_ci * @exit: called to cleanup everything done in init
2728c2ecf20Sopenharmony_ci * @get_ufs_hci_version: called to get UFS HCI version
2738c2ecf20Sopenharmony_ci * @clk_scale_notify: notifies that clks are scaled up/down
2748c2ecf20Sopenharmony_ci * @setup_clocks: called before touching any of the controller registers
2758c2ecf20Sopenharmony_ci * @setup_regulators: called before accessing the host controller
2768c2ecf20Sopenharmony_ci * @hce_enable_notify: called before and after HCE enable bit is set to allow
2778c2ecf20Sopenharmony_ci *                     variant specific Uni-Pro initialization.
2788c2ecf20Sopenharmony_ci * @link_startup_notify: called before and after Link startup is carried out
2798c2ecf20Sopenharmony_ci *                       to allow variant specific Uni-Pro initialization.
2808c2ecf20Sopenharmony_ci * @pwr_change_notify: called before and after a power mode change
2818c2ecf20Sopenharmony_ci *			is carried out to allow vendor spesific capabilities
2828c2ecf20Sopenharmony_ci *			to be set.
2838c2ecf20Sopenharmony_ci * @setup_xfer_req: called before any transfer request is issued
2848c2ecf20Sopenharmony_ci *                  to set some things
2858c2ecf20Sopenharmony_ci * @setup_task_mgmt: called before any task management request is issued
2868c2ecf20Sopenharmony_ci *                  to set some things
2878c2ecf20Sopenharmony_ci * @hibern8_notify: called around hibern8 enter/exit
2888c2ecf20Sopenharmony_ci * @apply_dev_quirks: called to apply device specific quirks
2898c2ecf20Sopenharmony_ci * @suspend: called during host controller PM callback
2908c2ecf20Sopenharmony_ci * @resume: called during host controller PM callback
2918c2ecf20Sopenharmony_ci * @dbg_register_dump: used to dump controller debug information
2928c2ecf20Sopenharmony_ci * @phy_initialization: used to initialize phys
2938c2ecf20Sopenharmony_ci * @device_reset: called to issue a reset pulse on the UFS device
2948c2ecf20Sopenharmony_ci * @program_key: program or evict an inline encryption key
2958c2ecf20Sopenharmony_ci */
2968c2ecf20Sopenharmony_cistruct ufs_hba_variant_ops {
2978c2ecf20Sopenharmony_ci	const char *name;
2988c2ecf20Sopenharmony_ci	int	(*init)(struct ufs_hba *);
2998c2ecf20Sopenharmony_ci	void    (*exit)(struct ufs_hba *);
3008c2ecf20Sopenharmony_ci	u32	(*get_ufs_hci_version)(struct ufs_hba *);
3018c2ecf20Sopenharmony_ci	int	(*clk_scale_notify)(struct ufs_hba *, bool,
3028c2ecf20Sopenharmony_ci				    enum ufs_notify_change_status);
3038c2ecf20Sopenharmony_ci	int	(*setup_clocks)(struct ufs_hba *, bool,
3048c2ecf20Sopenharmony_ci				enum ufs_notify_change_status);
3058c2ecf20Sopenharmony_ci	int     (*setup_regulators)(struct ufs_hba *, bool);
3068c2ecf20Sopenharmony_ci	int	(*hce_enable_notify)(struct ufs_hba *,
3078c2ecf20Sopenharmony_ci				     enum ufs_notify_change_status);
3088c2ecf20Sopenharmony_ci	int	(*link_startup_notify)(struct ufs_hba *,
3098c2ecf20Sopenharmony_ci				       enum ufs_notify_change_status);
3108c2ecf20Sopenharmony_ci	int	(*pwr_change_notify)(struct ufs_hba *,
3118c2ecf20Sopenharmony_ci					enum ufs_notify_change_status status,
3128c2ecf20Sopenharmony_ci					struct ufs_pa_layer_attr *,
3138c2ecf20Sopenharmony_ci					struct ufs_pa_layer_attr *);
3148c2ecf20Sopenharmony_ci	void	(*setup_xfer_req)(struct ufs_hba *, int, bool);
3158c2ecf20Sopenharmony_ci	void	(*setup_task_mgmt)(struct ufs_hba *, int, u8);
3168c2ecf20Sopenharmony_ci	void    (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme,
3178c2ecf20Sopenharmony_ci					enum ufs_notify_change_status);
3188c2ecf20Sopenharmony_ci	int	(*apply_dev_quirks)(struct ufs_hba *hba);
3198c2ecf20Sopenharmony_ci	void	(*fixup_dev_quirks)(struct ufs_hba *hba);
3208c2ecf20Sopenharmony_ci	int     (*suspend)(struct ufs_hba *, enum ufs_pm_op);
3218c2ecf20Sopenharmony_ci	int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
3228c2ecf20Sopenharmony_ci	void	(*dbg_register_dump)(struct ufs_hba *hba);
3238c2ecf20Sopenharmony_ci	int	(*phy_initialization)(struct ufs_hba *);
3248c2ecf20Sopenharmony_ci	int	(*device_reset)(struct ufs_hba *hba);
3258c2ecf20Sopenharmony_ci	void	(*config_scaling_param)(struct ufs_hba *hba,
3268c2ecf20Sopenharmony_ci					struct devfreq_dev_profile *profile,
3278c2ecf20Sopenharmony_ci					void *data);
3288c2ecf20Sopenharmony_ci	int	(*program_key)(struct ufs_hba *hba,
3298c2ecf20Sopenharmony_ci			       const union ufs_crypto_cfg_entry *cfg, int slot);
3308c2ecf20Sopenharmony_ci};
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci/* clock gating state  */
3338c2ecf20Sopenharmony_cienum clk_gating_state {
3348c2ecf20Sopenharmony_ci	CLKS_OFF,
3358c2ecf20Sopenharmony_ci	CLKS_ON,
3368c2ecf20Sopenharmony_ci	REQ_CLKS_OFF,
3378c2ecf20Sopenharmony_ci	REQ_CLKS_ON,
3388c2ecf20Sopenharmony_ci};
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci/**
3418c2ecf20Sopenharmony_ci * struct ufs_clk_gating - UFS clock gating related info
3428c2ecf20Sopenharmony_ci * @gate_work: worker to turn off clocks after some delay as specified in
3438c2ecf20Sopenharmony_ci * delay_ms
3448c2ecf20Sopenharmony_ci * @ungate_work: worker to turn on clocks that will be used in case of
3458c2ecf20Sopenharmony_ci * interrupt context
3468c2ecf20Sopenharmony_ci * @state: the current clocks state
3478c2ecf20Sopenharmony_ci * @delay_ms: gating delay in ms
3488c2ecf20Sopenharmony_ci * @is_suspended: clk gating is suspended when set to 1 which can be used
3498c2ecf20Sopenharmony_ci * during suspend/resume
3508c2ecf20Sopenharmony_ci * @delay_attr: sysfs attribute to control delay_attr
3518c2ecf20Sopenharmony_ci * @enable_attr: sysfs attribute to enable/disable clock gating
3528c2ecf20Sopenharmony_ci * @is_enabled: Indicates the current status of clock gating
3538c2ecf20Sopenharmony_ci * @active_reqs: number of requests that are pending and should be waited for
3548c2ecf20Sopenharmony_ci * completion before gating clocks.
3558c2ecf20Sopenharmony_ci */
3568c2ecf20Sopenharmony_cistruct ufs_clk_gating {
3578c2ecf20Sopenharmony_ci	struct delayed_work gate_work;
3588c2ecf20Sopenharmony_ci	struct work_struct ungate_work;
3598c2ecf20Sopenharmony_ci	enum clk_gating_state state;
3608c2ecf20Sopenharmony_ci	unsigned long delay_ms;
3618c2ecf20Sopenharmony_ci	bool is_suspended;
3628c2ecf20Sopenharmony_ci	struct device_attribute delay_attr;
3638c2ecf20Sopenharmony_ci	struct device_attribute enable_attr;
3648c2ecf20Sopenharmony_ci	bool is_enabled;
3658c2ecf20Sopenharmony_ci	int active_reqs;
3668c2ecf20Sopenharmony_ci	struct workqueue_struct *clk_gating_workq;
3678c2ecf20Sopenharmony_ci};
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistruct ufs_saved_pwr_info {
3708c2ecf20Sopenharmony_ci	struct ufs_pa_layer_attr info;
3718c2ecf20Sopenharmony_ci	bool is_valid;
3728c2ecf20Sopenharmony_ci};
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci/**
3758c2ecf20Sopenharmony_ci * struct ufs_clk_scaling - UFS clock scaling related data
3768c2ecf20Sopenharmony_ci * @active_reqs: number of requests that are pending. If this is zero when
3778c2ecf20Sopenharmony_ci * devfreq ->target() function is called then schedule "suspend_work" to
3788c2ecf20Sopenharmony_ci * suspend devfreq.
3798c2ecf20Sopenharmony_ci * @tot_busy_t: Total busy time in current polling window
3808c2ecf20Sopenharmony_ci * @window_start_t: Start time (in jiffies) of the current polling window
3818c2ecf20Sopenharmony_ci * @busy_start_t: Start time of current busy period
3828c2ecf20Sopenharmony_ci * @enable_attr: sysfs attribute to enable/disable clock scaling
3838c2ecf20Sopenharmony_ci * @saved_pwr_info: UFS power mode may also be changed during scaling and this
3848c2ecf20Sopenharmony_ci * one keeps track of previous power mode.
3858c2ecf20Sopenharmony_ci * @workq: workqueue to schedule devfreq suspend/resume work
3868c2ecf20Sopenharmony_ci * @suspend_work: worker to suspend devfreq
3878c2ecf20Sopenharmony_ci * @resume_work: worker to resume devfreq
3888c2ecf20Sopenharmony_ci * @is_allowed: tracks if scaling is currently allowed or not
3898c2ecf20Sopenharmony_ci * @is_busy_started: tracks if busy period has started or not
3908c2ecf20Sopenharmony_ci * @is_suspended: tracks if devfreq is suspended or not
3918c2ecf20Sopenharmony_ci */
3928c2ecf20Sopenharmony_cistruct ufs_clk_scaling {
3938c2ecf20Sopenharmony_ci	int active_reqs;
3948c2ecf20Sopenharmony_ci	unsigned long tot_busy_t;
3958c2ecf20Sopenharmony_ci	ktime_t window_start_t;
3968c2ecf20Sopenharmony_ci	ktime_t busy_start_t;
3978c2ecf20Sopenharmony_ci	struct device_attribute enable_attr;
3988c2ecf20Sopenharmony_ci	struct ufs_saved_pwr_info saved_pwr_info;
3998c2ecf20Sopenharmony_ci	struct workqueue_struct *workq;
4008c2ecf20Sopenharmony_ci	struct work_struct suspend_work;
4018c2ecf20Sopenharmony_ci	struct work_struct resume_work;
4028c2ecf20Sopenharmony_ci	bool is_allowed;
4038c2ecf20Sopenharmony_ci	bool is_busy_started;
4048c2ecf20Sopenharmony_ci	bool is_suspended;
4058c2ecf20Sopenharmony_ci};
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci#define UFS_ERR_REG_HIST_LENGTH 8
4088c2ecf20Sopenharmony_ci/**
4098c2ecf20Sopenharmony_ci * struct ufs_err_reg_hist - keeps history of errors
4108c2ecf20Sopenharmony_ci * @pos: index to indicate cyclic buffer position
4118c2ecf20Sopenharmony_ci * @reg: cyclic buffer for registers value
4128c2ecf20Sopenharmony_ci * @tstamp: cyclic buffer for time stamp
4138c2ecf20Sopenharmony_ci */
4148c2ecf20Sopenharmony_cistruct ufs_err_reg_hist {
4158c2ecf20Sopenharmony_ci	int pos;
4168c2ecf20Sopenharmony_ci	u32 reg[UFS_ERR_REG_HIST_LENGTH];
4178c2ecf20Sopenharmony_ci	ktime_t tstamp[UFS_ERR_REG_HIST_LENGTH];
4188c2ecf20Sopenharmony_ci};
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci/**
4218c2ecf20Sopenharmony_ci * struct ufs_stats - keeps usage/err statistics
4228c2ecf20Sopenharmony_ci * @last_intr_status: record the last interrupt status.
4238c2ecf20Sopenharmony_ci * @last_intr_ts: record the last interrupt timestamp.
4248c2ecf20Sopenharmony_ci * @hibern8_exit_cnt: Counter to keep track of number of exits,
4258c2ecf20Sopenharmony_ci *		reset this after link-startup.
4268c2ecf20Sopenharmony_ci * @last_hibern8_exit_tstamp: Set time after the hibern8 exit.
4278c2ecf20Sopenharmony_ci *		Clear after the first successful command completion.
4288c2ecf20Sopenharmony_ci * @pa_err: tracks pa-uic errors
4298c2ecf20Sopenharmony_ci * @dl_err: tracks dl-uic errors
4308c2ecf20Sopenharmony_ci * @nl_err: tracks nl-uic errors
4318c2ecf20Sopenharmony_ci * @tl_err: tracks tl-uic errors
4328c2ecf20Sopenharmony_ci * @dme_err: tracks dme errors
4338c2ecf20Sopenharmony_ci * @auto_hibern8_err: tracks auto-hibernate errors
4348c2ecf20Sopenharmony_ci * @fatal_err: tracks fatal errors
4358c2ecf20Sopenharmony_ci * @linkup_err: tracks link-startup errors
4368c2ecf20Sopenharmony_ci * @resume_err: tracks resume errors
4378c2ecf20Sopenharmony_ci * @suspend_err: tracks suspend errors
4388c2ecf20Sopenharmony_ci * @dev_reset: tracks device reset events
4398c2ecf20Sopenharmony_ci * @host_reset: tracks host reset events
4408c2ecf20Sopenharmony_ci * @tsk_abort: tracks task abort events
4418c2ecf20Sopenharmony_ci */
4428c2ecf20Sopenharmony_cistruct ufs_stats {
4438c2ecf20Sopenharmony_ci	u32 last_intr_status;
4448c2ecf20Sopenharmony_ci	ktime_t last_intr_ts;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	u32 hibern8_exit_cnt;
4478c2ecf20Sopenharmony_ci	ktime_t last_hibern8_exit_tstamp;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	/* uic specific errors */
4508c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist pa_err;
4518c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist dl_err;
4528c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist nl_err;
4538c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist tl_err;
4548c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist dme_err;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	/* fatal errors */
4578c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist auto_hibern8_err;
4588c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist fatal_err;
4598c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist link_startup_err;
4608c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist resume_err;
4618c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist suspend_err;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	/* abnormal events */
4648c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist dev_reset;
4658c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist host_reset;
4668c2ecf20Sopenharmony_ci	struct ufs_err_reg_hist task_abort;
4678c2ecf20Sopenharmony_ci};
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_cienum ufshcd_quirks {
4708c2ecf20Sopenharmony_ci	/* Interrupt aggregation support is broken */
4718c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_INTR_AGGR			= 1 << 0,
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	/*
4748c2ecf20Sopenharmony_ci	 * delay before each dme command is required as the unipro
4758c2ecf20Sopenharmony_ci	 * layer has shown instabilities
4768c2ecf20Sopenharmony_ci	 */
4778c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS		= 1 << 1,
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	/*
4808c2ecf20Sopenharmony_ci	 * If UFS host controller is having issue in processing LCC (Line
4818c2ecf20Sopenharmony_ci	 * Control Command) coming from device then enable this quirk.
4828c2ecf20Sopenharmony_ci	 * When this quirk is enabled, host controller driver should disable
4838c2ecf20Sopenharmony_ci	 * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
4848c2ecf20Sopenharmony_ci	 * attribute of device to 0).
4858c2ecf20Sopenharmony_ci	 */
4868c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_LCC				= 1 << 2,
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	/*
4898c2ecf20Sopenharmony_ci	 * The attribute PA_RXHSUNTERMCAP specifies whether or not the
4908c2ecf20Sopenharmony_ci	 * inbound Link supports unterminated line in HS mode. Setting this
4918c2ecf20Sopenharmony_ci	 * attribute to 1 fixes moving to HS gear.
4928c2ecf20Sopenharmony_ci	 */
4938c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP		= 1 << 3,
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	/*
4968c2ecf20Sopenharmony_ci	 * This quirk needs to be enabled if the host controller only allows
4978c2ecf20Sopenharmony_ci	 * accessing the peer dme attributes in AUTO mode (FAST AUTO or
4988c2ecf20Sopenharmony_ci	 * SLOW AUTO).
4998c2ecf20Sopenharmony_ci	 */
5008c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE		= 1 << 4,
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/*
5038c2ecf20Sopenharmony_ci	 * This quirk needs to be enabled if the host controller doesn't
5048c2ecf20Sopenharmony_ci	 * advertise the correct version in UFS_VER register. If this quirk
5058c2ecf20Sopenharmony_ci	 * is enabled, standard UFS host driver will call the vendor specific
5068c2ecf20Sopenharmony_ci	 * ops (get_ufs_hci_version) to get the correct version.
5078c2ecf20Sopenharmony_ci	 */
5088c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION		= 1 << 5,
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	/*
5118c2ecf20Sopenharmony_ci	 * Clear handling for transfer/task request list is just opposite.
5128c2ecf20Sopenharmony_ci	 */
5138c2ecf20Sopenharmony_ci	UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR		= 1 << 6,
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/*
5168c2ecf20Sopenharmony_ci	 * This quirk needs to be enabled if host controller doesn't allow
5178c2ecf20Sopenharmony_ci	 * that the interrupt aggregation timer and counter are reset by s/w.
5188c2ecf20Sopenharmony_ci	 */
5198c2ecf20Sopenharmony_ci	UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR		= 1 << 7,
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	/*
5228c2ecf20Sopenharmony_ci	 * This quirks needs to be enabled if host controller cannot be
5238c2ecf20Sopenharmony_ci	 * enabled via HCE register.
5248c2ecf20Sopenharmony_ci	 */
5258c2ecf20Sopenharmony_ci	UFSHCI_QUIRK_BROKEN_HCE				= 1 << 8,
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	/*
5288c2ecf20Sopenharmony_ci	 * This quirk needs to be enabled if the host controller regards
5298c2ecf20Sopenharmony_ci	 * resolution of the values of PRDTO and PRDTL in UTRD as byte.
5308c2ecf20Sopenharmony_ci	 */
5318c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_PRDT_BYTE_GRAN			= 1 << 9,
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	/*
5348c2ecf20Sopenharmony_ci	 * This quirk needs to be enabled if the host controller reports
5358c2ecf20Sopenharmony_ci	 * OCS FATAL ERROR with device error through sense data
5368c2ecf20Sopenharmony_ci	 */
5378c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR		= 1 << 10,
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	/*
5408c2ecf20Sopenharmony_ci	 * This quirk needs to be enabled if the host controller has
5418c2ecf20Sopenharmony_ci	 * auto-hibernate capability but it doesn't work.
5428c2ecf20Sopenharmony_ci	 */
5438c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8		= 1 << 11,
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	/*
5468c2ecf20Sopenharmony_ci	 * This quirk needs to disable manual flush for write booster
5478c2ecf20Sopenharmony_ci	 */
5488c2ecf20Sopenharmony_ci	UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL		= 1 << 12,
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	/*
5518c2ecf20Sopenharmony_ci	 * This quirk needs to disable unipro timeout values
5528c2ecf20Sopenharmony_ci	 * before power mode change
5538c2ecf20Sopenharmony_ci	 */
5548c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13,
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	/*
5578c2ecf20Sopenharmony_ci	 * This quirk allows only sg entries aligned with page size.
5588c2ecf20Sopenharmony_ci	 */
5598c2ecf20Sopenharmony_ci	UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE		= 1 << 14,
5608c2ecf20Sopenharmony_ci};
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_cienum ufshcd_caps {
5638c2ecf20Sopenharmony_ci	/* Allow dynamic clk gating */
5648c2ecf20Sopenharmony_ci	UFSHCD_CAP_CLK_GATING				= 1 << 0,
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	/* Allow hiberb8 with clk gating */
5678c2ecf20Sopenharmony_ci	UFSHCD_CAP_HIBERN8_WITH_CLK_GATING		= 1 << 1,
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	/* Allow dynamic clk scaling */
5708c2ecf20Sopenharmony_ci	UFSHCD_CAP_CLK_SCALING				= 1 << 2,
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	/* Allow auto bkops to enabled during runtime suspend */
5738c2ecf20Sopenharmony_ci	UFSHCD_CAP_AUTO_BKOPS_SUSPEND			= 1 << 3,
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/*
5768c2ecf20Sopenharmony_ci	 * This capability allows host controller driver to use the UFS HCI's
5778c2ecf20Sopenharmony_ci	 * interrupt aggregation capability.
5788c2ecf20Sopenharmony_ci	 * CAUTION: Enabling this might reduce overall UFS throughput.
5798c2ecf20Sopenharmony_ci	 */
5808c2ecf20Sopenharmony_ci	UFSHCD_CAP_INTR_AGGR				= 1 << 4,
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	/*
5838c2ecf20Sopenharmony_ci	 * This capability allows the device auto-bkops to be always enabled
5848c2ecf20Sopenharmony_ci	 * except during suspend (both runtime and suspend).
5858c2ecf20Sopenharmony_ci	 * Enabling this capability means that device will always be allowed
5868c2ecf20Sopenharmony_ci	 * to do background operation when it's active but it might degrade
5878c2ecf20Sopenharmony_ci	 * the performance of ongoing read/write operations.
5888c2ecf20Sopenharmony_ci	 */
5898c2ecf20Sopenharmony_ci	UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND = 1 << 5,
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	/*
5928c2ecf20Sopenharmony_ci	 * This capability allows host controller driver to automatically
5938c2ecf20Sopenharmony_ci	 * enable runtime power management by itself instead of waiting
5948c2ecf20Sopenharmony_ci	 * for userspace to control the power management.
5958c2ecf20Sopenharmony_ci	 */
5968c2ecf20Sopenharmony_ci	UFSHCD_CAP_RPM_AUTOSUSPEND			= 1 << 6,
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	/*
5998c2ecf20Sopenharmony_ci	 * This capability allows the host controller driver to turn-on
6008c2ecf20Sopenharmony_ci	 * WriteBooster, if the underlying device supports it and is
6018c2ecf20Sopenharmony_ci	 * provisioned to be used. This would increase the write performance.
6028c2ecf20Sopenharmony_ci	 */
6038c2ecf20Sopenharmony_ci	UFSHCD_CAP_WB_EN				= 1 << 7,
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	/*
6068c2ecf20Sopenharmony_ci	 * This capability allows the host controller driver to use the
6078c2ecf20Sopenharmony_ci	 * inline crypto engine, if it is present
6088c2ecf20Sopenharmony_ci	 */
6098c2ecf20Sopenharmony_ci	UFSHCD_CAP_CRYPTO				= 1 << 8,
6108c2ecf20Sopenharmony_ci};
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cistruct ufs_hba_variant_params {
6138c2ecf20Sopenharmony_ci	struct devfreq_dev_profile devfreq_profile;
6148c2ecf20Sopenharmony_ci	struct devfreq_simple_ondemand_data ondemand_data;
6158c2ecf20Sopenharmony_ci	u16 hba_enable_delay_us;
6168c2ecf20Sopenharmony_ci	u32 wb_flush_threshold;
6178c2ecf20Sopenharmony_ci};
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci/**
6208c2ecf20Sopenharmony_ci * struct ufs_hba - per adapter private structure
6218c2ecf20Sopenharmony_ci * @mmio_base: UFSHCI base register address
6228c2ecf20Sopenharmony_ci * @ucdl_base_addr: UFS Command Descriptor base address
6238c2ecf20Sopenharmony_ci * @utrdl_base_addr: UTP Transfer Request Descriptor base address
6248c2ecf20Sopenharmony_ci * @utmrdl_base_addr: UTP Task Management Descriptor base address
6258c2ecf20Sopenharmony_ci * @ucdl_dma_addr: UFS Command Descriptor DMA address
6268c2ecf20Sopenharmony_ci * @utrdl_dma_addr: UTRDL DMA address
6278c2ecf20Sopenharmony_ci * @utmrdl_dma_addr: UTMRDL DMA address
6288c2ecf20Sopenharmony_ci * @host: Scsi_Host instance of the driver
6298c2ecf20Sopenharmony_ci * @dev: device handle
6308c2ecf20Sopenharmony_ci * @lrb: local reference block
6318c2ecf20Sopenharmony_ci * @cmd_queue: Used to allocate command tags from hba->host->tag_set.
6328c2ecf20Sopenharmony_ci * @outstanding_tasks: Bits representing outstanding task requests
6338c2ecf20Sopenharmony_ci * @outstanding_reqs: Bits representing outstanding transfer requests
6348c2ecf20Sopenharmony_ci * @capabilities: UFS Controller Capabilities
6358c2ecf20Sopenharmony_ci * @nutrs: Transfer Request Queue depth supported by controller
6368c2ecf20Sopenharmony_ci * @nutmrs: Task Management Queue depth supported by controller
6378c2ecf20Sopenharmony_ci * @ufs_version: UFS Version to which controller complies
6388c2ecf20Sopenharmony_ci * @vops: pointer to variant specific operations
6398c2ecf20Sopenharmony_ci * @priv: pointer to variant specific private data
6408c2ecf20Sopenharmony_ci * @irq: Irq number of the controller
6418c2ecf20Sopenharmony_ci * @active_uic_cmd: handle of active UIC command
6428c2ecf20Sopenharmony_ci * @uic_cmd_mutex: mutex for uic command
6438c2ecf20Sopenharmony_ci * @tmf_tag_set: TMF tag set.
6448c2ecf20Sopenharmony_ci * @tmf_queue: Used to allocate TMF tags.
6458c2ecf20Sopenharmony_ci * @pwr_done: completion for power mode change
6468c2ecf20Sopenharmony_ci * @ufshcd_state: UFSHCD states
6478c2ecf20Sopenharmony_ci * @eh_flags: Error handling flags
6488c2ecf20Sopenharmony_ci * @intr_mask: Interrupt Mask Bits
6498c2ecf20Sopenharmony_ci * @ee_ctrl_mask: Exception event control mask
6508c2ecf20Sopenharmony_ci * @is_powered: flag to check if HBA is powered
6518c2ecf20Sopenharmony_ci * @eh_wq: Workqueue that eh_work works on
6528c2ecf20Sopenharmony_ci * @eh_work: Worker to handle UFS errors that require s/w attention
6538c2ecf20Sopenharmony_ci * @eeh_work: Worker to handle exception events
6548c2ecf20Sopenharmony_ci * @errors: HBA errors
6558c2ecf20Sopenharmony_ci * @uic_error: UFS interconnect layer error status
6568c2ecf20Sopenharmony_ci * @saved_err: sticky error mask
6578c2ecf20Sopenharmony_ci * @saved_uic_err: sticky UIC error mask
6588c2ecf20Sopenharmony_ci * @force_reset: flag to force eh_work perform a full reset
6598c2ecf20Sopenharmony_ci * @force_pmc: flag to force a power mode change
6608c2ecf20Sopenharmony_ci * @silence_err_logs: flag to silence error logs
6618c2ecf20Sopenharmony_ci * @dev_cmd: ufs device management command information
6628c2ecf20Sopenharmony_ci * @last_dme_cmd_tstamp: time stamp of the last completed DME command
6638c2ecf20Sopenharmony_ci * @auto_bkops_enabled: to track whether bkops is enabled in device
6648c2ecf20Sopenharmony_ci * @vreg_info: UFS device voltage regulator information
6658c2ecf20Sopenharmony_ci * @clk_list_head: UFS host controller clocks list node head
6668c2ecf20Sopenharmony_ci * @pwr_info: holds current power mode
6678c2ecf20Sopenharmony_ci * @max_pwr_info: keeps the device max valid pwm
6688c2ecf20Sopenharmony_ci * @desc_size: descriptor sizes reported by device
6698c2ecf20Sopenharmony_ci * @urgent_bkops_lvl: keeps track of urgent bkops level for device
6708c2ecf20Sopenharmony_ci * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
6718c2ecf20Sopenharmony_ci *  device is known or not.
6728c2ecf20Sopenharmony_ci * @scsi_block_reqs_cnt: reference counting for scsi block requests
6738c2ecf20Sopenharmony_ci * @crypto_capabilities: Content of crypto capabilities register (0x100)
6748c2ecf20Sopenharmony_ci * @crypto_cap_array: Array of crypto capabilities
6758c2ecf20Sopenharmony_ci * @crypto_cfg_register: Start of the crypto cfg array
6768c2ecf20Sopenharmony_ci * @ksm: the keyslot manager tied to this hba
6778c2ecf20Sopenharmony_ci */
6788c2ecf20Sopenharmony_cistruct ufs_hba {
6798c2ecf20Sopenharmony_ci	void __iomem *mmio_base;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	/* Virtual memory reference */
6828c2ecf20Sopenharmony_ci	struct utp_transfer_cmd_desc *ucdl_base_addr;
6838c2ecf20Sopenharmony_ci	struct utp_transfer_req_desc *utrdl_base_addr;
6848c2ecf20Sopenharmony_ci	struct utp_task_req_desc *utmrdl_base_addr;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	/* DMA memory reference */
6878c2ecf20Sopenharmony_ci	dma_addr_t ucdl_dma_addr;
6888c2ecf20Sopenharmony_ci	dma_addr_t utrdl_dma_addr;
6898c2ecf20Sopenharmony_ci	dma_addr_t utmrdl_dma_addr;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	struct Scsi_Host *host;
6928c2ecf20Sopenharmony_ci	struct device *dev;
6938c2ecf20Sopenharmony_ci	struct request_queue *cmd_queue;
6948c2ecf20Sopenharmony_ci	/*
6958c2ecf20Sopenharmony_ci	 * This field is to keep a reference to "scsi_device" corresponding to
6968c2ecf20Sopenharmony_ci	 * "UFS device" W-LU.
6978c2ecf20Sopenharmony_ci	 */
6988c2ecf20Sopenharmony_ci	struct scsi_device *sdev_ufs_device;
6998c2ecf20Sopenharmony_ci	struct scsi_device *sdev_rpmb;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	enum ufs_dev_pwr_mode curr_dev_pwr_mode;
7028c2ecf20Sopenharmony_ci	enum uic_link_state uic_link_state;
7038c2ecf20Sopenharmony_ci	/* Desired UFS power management level during runtime PM */
7048c2ecf20Sopenharmony_ci	enum ufs_pm_level rpm_lvl;
7058c2ecf20Sopenharmony_ci	/* Desired UFS power management level during system PM */
7068c2ecf20Sopenharmony_ci	enum ufs_pm_level spm_lvl;
7078c2ecf20Sopenharmony_ci	struct device_attribute rpm_lvl_attr;
7088c2ecf20Sopenharmony_ci	struct device_attribute spm_lvl_attr;
7098c2ecf20Sopenharmony_ci	int pm_op_in_progress;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	/* Auto-Hibernate Idle Timer register value */
7128c2ecf20Sopenharmony_ci	u32 ahit;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	struct ufshcd_lrb *lrb;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	unsigned long outstanding_tasks;
7178c2ecf20Sopenharmony_ci	unsigned long outstanding_reqs;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	u32 capabilities;
7208c2ecf20Sopenharmony_ci	int nutrs;
7218c2ecf20Sopenharmony_ci	int nutmrs;
7228c2ecf20Sopenharmony_ci	u32 ufs_version;
7238c2ecf20Sopenharmony_ci	const struct ufs_hba_variant_ops *vops;
7248c2ecf20Sopenharmony_ci	struct ufs_hba_variant_params *vps;
7258c2ecf20Sopenharmony_ci	void *priv;
7268c2ecf20Sopenharmony_ci	unsigned int irq;
7278c2ecf20Sopenharmony_ci	bool is_irq_enabled;
7288c2ecf20Sopenharmony_ci	enum ufs_ref_clk_freq dev_ref_clk_freq;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	unsigned int quirks;	/* Deviations from standard UFSHCI spec. */
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	/* Device deviations from standard UFS device spec. */
7338c2ecf20Sopenharmony_ci	unsigned int dev_quirks;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	struct blk_mq_tag_set tmf_tag_set;
7368c2ecf20Sopenharmony_ci	struct request_queue *tmf_queue;
7378c2ecf20Sopenharmony_ci	struct request **tmf_rqs;
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	struct uic_command *active_uic_cmd;
7408c2ecf20Sopenharmony_ci	struct mutex uic_cmd_mutex;
7418c2ecf20Sopenharmony_ci	struct completion *uic_async_done;
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	u32 ufshcd_state;
7448c2ecf20Sopenharmony_ci	u32 eh_flags;
7458c2ecf20Sopenharmony_ci	u32 intr_mask;
7468c2ecf20Sopenharmony_ci	u16 ee_ctrl_mask;
7478c2ecf20Sopenharmony_ci	bool is_powered;
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	/* Work Queues */
7508c2ecf20Sopenharmony_ci	struct workqueue_struct *eh_wq;
7518c2ecf20Sopenharmony_ci	struct work_struct eh_work;
7528c2ecf20Sopenharmony_ci	struct work_struct eeh_work;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	/* HBA Errors */
7558c2ecf20Sopenharmony_ci	u32 errors;
7568c2ecf20Sopenharmony_ci	u32 uic_error;
7578c2ecf20Sopenharmony_ci	u32 saved_err;
7588c2ecf20Sopenharmony_ci	u32 saved_uic_err;
7598c2ecf20Sopenharmony_ci	struct ufs_stats ufs_stats;
7608c2ecf20Sopenharmony_ci	bool force_reset;
7618c2ecf20Sopenharmony_ci	bool force_pmc;
7628c2ecf20Sopenharmony_ci	bool silence_err_logs;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	/* Device management request data */
7658c2ecf20Sopenharmony_ci	struct ufs_dev_cmd dev_cmd;
7668c2ecf20Sopenharmony_ci	ktime_t last_dme_cmd_tstamp;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	/* Keeps information of the UFS device connected to this host */
7698c2ecf20Sopenharmony_ci	struct ufs_dev_info dev_info;
7708c2ecf20Sopenharmony_ci	bool auto_bkops_enabled;
7718c2ecf20Sopenharmony_ci	struct ufs_vreg_info vreg_info;
7728c2ecf20Sopenharmony_ci	struct list_head clk_list_head;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	bool wlun_dev_clr_ua;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	/* Number of requests aborts */
7778c2ecf20Sopenharmony_ci	int req_abort_count;
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	/* Number of lanes available (1 or 2) for Rx/Tx */
7808c2ecf20Sopenharmony_ci	u32 lanes_per_direction;
7818c2ecf20Sopenharmony_ci	struct ufs_pa_layer_attr pwr_info;
7828c2ecf20Sopenharmony_ci	struct ufs_pwr_mode_info max_pwr_info;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	struct ufs_clk_gating clk_gating;
7858c2ecf20Sopenharmony_ci	/* Control to enable/disable host capabilities */
7868c2ecf20Sopenharmony_ci	u32 caps;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	struct devfreq *devfreq;
7898c2ecf20Sopenharmony_ci	struct ufs_clk_scaling clk_scaling;
7908c2ecf20Sopenharmony_ci	bool is_sys_suspended;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	enum bkops_status urgent_bkops_lvl;
7938c2ecf20Sopenharmony_ci	bool is_urgent_bkops_lvl_checked;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	struct rw_semaphore clk_scaling_lock;
7968c2ecf20Sopenharmony_ci	unsigned char desc_size[QUERY_DESC_IDN_MAX];
7978c2ecf20Sopenharmony_ci	atomic_t scsi_block_reqs_cnt;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	struct device		bsg_dev;
8008c2ecf20Sopenharmony_ci	struct request_queue	*bsg_queue;
8018c2ecf20Sopenharmony_ci	bool wb_buf_flush_enabled;
8028c2ecf20Sopenharmony_ci	bool wb_enabled;
8038c2ecf20Sopenharmony_ci	struct delayed_work rpm_dev_flush_recheck_work;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_UFS_CRYPTO
8068c2ecf20Sopenharmony_ci	union ufs_crypto_capabilities crypto_capabilities;
8078c2ecf20Sopenharmony_ci	union ufs_crypto_cap_entry *crypto_cap_array;
8088c2ecf20Sopenharmony_ci	u32 crypto_cfg_register;
8098c2ecf20Sopenharmony_ci	struct blk_keyslot_manager ksm;
8108c2ecf20Sopenharmony_ci#endif
8118c2ecf20Sopenharmony_ci};
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci/* Returns true if clocks can be gated. Otherwise false */
8148c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba)
8158c2ecf20Sopenharmony_ci{
8168c2ecf20Sopenharmony_ci	return hba->caps & UFSHCD_CAP_CLK_GATING;
8178c2ecf20Sopenharmony_ci}
8188c2ecf20Sopenharmony_cistatic inline bool ufshcd_can_hibern8_during_gating(struct ufs_hba *hba)
8198c2ecf20Sopenharmony_ci{
8208c2ecf20Sopenharmony_ci	return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
8218c2ecf20Sopenharmony_ci}
8228c2ecf20Sopenharmony_cistatic inline int ufshcd_is_clkscaling_supported(struct ufs_hba *hba)
8238c2ecf20Sopenharmony_ci{
8248c2ecf20Sopenharmony_ci	return hba->caps & UFSHCD_CAP_CLK_SCALING;
8258c2ecf20Sopenharmony_ci}
8268c2ecf20Sopenharmony_cistatic inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba)
8278c2ecf20Sopenharmony_ci{
8288c2ecf20Sopenharmony_ci	return hba->caps & UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
8298c2ecf20Sopenharmony_ci}
8308c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba)
8318c2ecf20Sopenharmony_ci{
8328c2ecf20Sopenharmony_ci	return hba->caps & UFSHCD_CAP_RPM_AUTOSUSPEND;
8338c2ecf20Sopenharmony_ci}
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba)
8368c2ecf20Sopenharmony_ci{
8378c2ecf20Sopenharmony_ci/* DWC UFS Core has the Interrupt aggregation feature but is not detectable*/
8388c2ecf20Sopenharmony_ci#ifndef CONFIG_SCSI_UFS_DWC
8398c2ecf20Sopenharmony_ci	if ((hba->caps & UFSHCD_CAP_INTR_AGGR) &&
8408c2ecf20Sopenharmony_ci	    !(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR))
8418c2ecf20Sopenharmony_ci		return true;
8428c2ecf20Sopenharmony_ci	else
8438c2ecf20Sopenharmony_ci		return false;
8448c2ecf20Sopenharmony_ci#else
8458c2ecf20Sopenharmony_cireturn true;
8468c2ecf20Sopenharmony_ci#endif
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) &&
8528c2ecf20Sopenharmony_ci		!(hba->quirks & UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8);
8538c2ecf20Sopenharmony_ci}
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba)
8568c2ecf20Sopenharmony_ci{
8578c2ecf20Sopenharmony_ci	return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false;
8588c2ecf20Sopenharmony_ci}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba)
8618c2ecf20Sopenharmony_ci{
8628c2ecf20Sopenharmony_ci	return hba->caps & UFSHCD_CAP_WB_EN;
8638c2ecf20Sopenharmony_ci}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci#define ufshcd_writel(hba, val, reg)	\
8668c2ecf20Sopenharmony_ci	writel((val), (hba)->mmio_base + (reg))
8678c2ecf20Sopenharmony_ci#define ufshcd_readl(hba, reg)	\
8688c2ecf20Sopenharmony_ci	readl((hba)->mmio_base + (reg))
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci/**
8718c2ecf20Sopenharmony_ci * ufshcd_rmwl - read modify write into a register
8728c2ecf20Sopenharmony_ci * @hba - per adapter instance
8738c2ecf20Sopenharmony_ci * @mask - mask to apply on read value
8748c2ecf20Sopenharmony_ci * @val - actual value to write
8758c2ecf20Sopenharmony_ci * @reg - register address
8768c2ecf20Sopenharmony_ci */
8778c2ecf20Sopenharmony_cistatic inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
8788c2ecf20Sopenharmony_ci{
8798c2ecf20Sopenharmony_ci	u32 tmp;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	tmp = ufshcd_readl(hba, reg);
8828c2ecf20Sopenharmony_ci	tmp &= ~mask;
8838c2ecf20Sopenharmony_ci	tmp |= (val & mask);
8848c2ecf20Sopenharmony_ci	ufshcd_writel(hba, tmp, reg);
8858c2ecf20Sopenharmony_ci}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ciint ufshcd_alloc_host(struct device *, struct ufs_hba **);
8888c2ecf20Sopenharmony_civoid ufshcd_dealloc_host(struct ufs_hba *);
8898c2ecf20Sopenharmony_ciint ufshcd_hba_enable(struct ufs_hba *hba);
8908c2ecf20Sopenharmony_ciint ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int);
8918c2ecf20Sopenharmony_ciint ufshcd_link_recovery(struct ufs_hba *hba);
8928c2ecf20Sopenharmony_ciint ufshcd_make_hba_operational(struct ufs_hba *hba);
8938c2ecf20Sopenharmony_civoid ufshcd_remove(struct ufs_hba *);
8948c2ecf20Sopenharmony_ciint ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
8958c2ecf20Sopenharmony_civoid ufshcd_delay_us(unsigned long us, unsigned long tolerance);
8968c2ecf20Sopenharmony_ciint ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
8978c2ecf20Sopenharmony_ci				u32 val, unsigned long interval_us,
8988c2ecf20Sopenharmony_ci				unsigned long timeout_ms);
8998c2ecf20Sopenharmony_civoid ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk);
9008c2ecf20Sopenharmony_civoid ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist,
9018c2ecf20Sopenharmony_ci			    u32 reg);
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_cistatic inline void check_upiu_size(void)
9048c2ecf20Sopenharmony_ci{
9058c2ecf20Sopenharmony_ci	BUILD_BUG_ON(ALIGNED_UPIU_SIZE <
9068c2ecf20Sopenharmony_ci		GENERAL_UPIU_REQUEST_SIZE + QUERY_DESC_MAX_SIZE);
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci/**
9108c2ecf20Sopenharmony_ci * ufshcd_set_variant - set variant specific data to the hba
9118c2ecf20Sopenharmony_ci * @hba - per adapter instance
9128c2ecf20Sopenharmony_ci * @variant - pointer to variant specific data
9138c2ecf20Sopenharmony_ci */
9148c2ecf20Sopenharmony_cistatic inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	BUG_ON(!hba);
9178c2ecf20Sopenharmony_ci	hba->priv = variant;
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci/**
9218c2ecf20Sopenharmony_ci * ufshcd_get_variant - get variant specific data from the hba
9228c2ecf20Sopenharmony_ci * @hba - per adapter instance
9238c2ecf20Sopenharmony_ci */
9248c2ecf20Sopenharmony_cistatic inline void *ufshcd_get_variant(struct ufs_hba *hba)
9258c2ecf20Sopenharmony_ci{
9268c2ecf20Sopenharmony_ci	BUG_ON(!hba);
9278c2ecf20Sopenharmony_ci	return hba->priv;
9288c2ecf20Sopenharmony_ci}
9298c2ecf20Sopenharmony_cistatic inline bool ufshcd_keep_autobkops_enabled_except_suspend(
9308c2ecf20Sopenharmony_ci							struct ufs_hba *hba)
9318c2ecf20Sopenharmony_ci{
9328c2ecf20Sopenharmony_ci	return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND;
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_LU_DEDICATED)
9388c2ecf20Sopenharmony_ci		return hba->dev_info.wb_dedicated_lu;
9398c2ecf20Sopenharmony_ci	return 0;
9408c2ecf20Sopenharmony_ci}
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ciextern int ufshcd_runtime_suspend(struct ufs_hba *hba);
9438c2ecf20Sopenharmony_ciextern int ufshcd_runtime_resume(struct ufs_hba *hba);
9448c2ecf20Sopenharmony_ciextern int ufshcd_runtime_idle(struct ufs_hba *hba);
9458c2ecf20Sopenharmony_ciextern int ufshcd_system_suspend(struct ufs_hba *hba);
9468c2ecf20Sopenharmony_ciextern int ufshcd_system_resume(struct ufs_hba *hba);
9478c2ecf20Sopenharmony_ciextern int ufshcd_shutdown(struct ufs_hba *hba);
9488c2ecf20Sopenharmony_ciextern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
9498c2ecf20Sopenharmony_ci			       u8 attr_set, u32 mib_val, u8 peer);
9508c2ecf20Sopenharmony_ciextern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
9518c2ecf20Sopenharmony_ci			       u32 *mib_val, u8 peer);
9528c2ecf20Sopenharmony_ciextern int ufshcd_config_pwr_mode(struct ufs_hba *hba,
9538c2ecf20Sopenharmony_ci			struct ufs_pa_layer_attr *desired_pwr_mode);
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci/* UIC command interfaces for DME primitives */
9568c2ecf20Sopenharmony_ci#define DME_LOCAL	0
9578c2ecf20Sopenharmony_ci#define DME_PEER	1
9588c2ecf20Sopenharmony_ci#define ATTR_SET_NOR	0	/* NORMAL */
9598c2ecf20Sopenharmony_ci#define ATTR_SET_ST	1	/* STATIC */
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_cistatic inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
9628c2ecf20Sopenharmony_ci				 u32 mib_val)
9638c2ecf20Sopenharmony_ci{
9648c2ecf20Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
9658c2ecf20Sopenharmony_ci				   mib_val, DME_LOCAL);
9668c2ecf20Sopenharmony_ci}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_cistatic inline int ufshcd_dme_st_set(struct ufs_hba *hba, u32 attr_sel,
9698c2ecf20Sopenharmony_ci				    u32 mib_val)
9708c2ecf20Sopenharmony_ci{
9718c2ecf20Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
9728c2ecf20Sopenharmony_ci				   mib_val, DME_LOCAL);
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_cistatic inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
9768c2ecf20Sopenharmony_ci				      u32 mib_val)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
9798c2ecf20Sopenharmony_ci				   mib_val, DME_PEER);
9808c2ecf20Sopenharmony_ci}
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_cistatic inline int ufshcd_dme_peer_st_set(struct ufs_hba *hba, u32 attr_sel,
9838c2ecf20Sopenharmony_ci					 u32 mib_val)
9848c2ecf20Sopenharmony_ci{
9858c2ecf20Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
9868c2ecf20Sopenharmony_ci				   mib_val, DME_PEER);
9878c2ecf20Sopenharmony_ci}
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_cistatic inline int ufshcd_dme_get(struct ufs_hba *hba,
9908c2ecf20Sopenharmony_ci				 u32 attr_sel, u32 *mib_val)
9918c2ecf20Sopenharmony_ci{
9928c2ecf20Sopenharmony_ci	return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL);
9938c2ecf20Sopenharmony_ci}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_cistatic inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
9968c2ecf20Sopenharmony_ci				      u32 attr_sel, u32 *mib_val)
9978c2ecf20Sopenharmony_ci{
9988c2ecf20Sopenharmony_ci	return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
9998c2ecf20Sopenharmony_ci}
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
10028c2ecf20Sopenharmony_ci{
10038c2ecf20Sopenharmony_ci	return (pwr_info->pwr_rx == FAST_MODE ||
10048c2ecf20Sopenharmony_ci		pwr_info->pwr_rx == FASTAUTO_MODE) &&
10058c2ecf20Sopenharmony_ci		(pwr_info->pwr_tx == FAST_MODE ||
10068c2ecf20Sopenharmony_ci		pwr_info->pwr_tx == FASTAUTO_MODE);
10078c2ecf20Sopenharmony_ci}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_cistatic inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba)
10108c2ecf20Sopenharmony_ci{
10118c2ecf20Sopenharmony_ci	return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
10128c2ecf20Sopenharmony_ci}
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci/* Expose Query-Request API */
10158c2ecf20Sopenharmony_ciint ufshcd_query_descriptor_retry(struct ufs_hba *hba,
10168c2ecf20Sopenharmony_ci				  enum query_opcode opcode,
10178c2ecf20Sopenharmony_ci				  enum desc_idn idn, u8 index,
10188c2ecf20Sopenharmony_ci				  u8 selector,
10198c2ecf20Sopenharmony_ci				  u8 *desc_buf, int *buf_len);
10208c2ecf20Sopenharmony_ciint ufshcd_read_desc_param(struct ufs_hba *hba,
10218c2ecf20Sopenharmony_ci			   enum desc_idn desc_id,
10228c2ecf20Sopenharmony_ci			   int desc_index,
10238c2ecf20Sopenharmony_ci			   u8 param_offset,
10248c2ecf20Sopenharmony_ci			   u8 *param_read_buf,
10258c2ecf20Sopenharmony_ci			   u8 param_size);
10268c2ecf20Sopenharmony_ciint ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
10278c2ecf20Sopenharmony_ci		      enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
10288c2ecf20Sopenharmony_ciint ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
10298c2ecf20Sopenharmony_ci	enum flag_idn idn, u8 index, bool *flag_res);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_civoid ufshcd_auto_hibern8_enable(struct ufs_hba *hba);
10328c2ecf20Sopenharmony_civoid ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
10338c2ecf20Sopenharmony_civoid ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups);
10348c2ecf20Sopenharmony_ci#define SD_ASCII_STD true
10358c2ecf20Sopenharmony_ci#define SD_RAW false
10368c2ecf20Sopenharmony_ciint ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
10378c2ecf20Sopenharmony_ci			    u8 **buf, bool ascii);
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ciint ufshcd_hold(struct ufs_hba *hba, bool async);
10408c2ecf20Sopenharmony_civoid ufshcd_release(struct ufs_hba *hba);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_civoid ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
10438c2ecf20Sopenharmony_ci				  int *desc_length);
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ciu32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ciint ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ciint ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
10508c2ecf20Sopenharmony_ci			     struct utp_upiu_req *req_upiu,
10518c2ecf20Sopenharmony_ci			     struct utp_upiu_req *rsp_upiu,
10528c2ecf20Sopenharmony_ci			     int msgcode,
10538c2ecf20Sopenharmony_ci			     u8 *desc_buff, int *buff_len,
10548c2ecf20Sopenharmony_ci			     enum query_opcode desc_op);
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci/* Wrapper functions for safely calling variant operations */
10578c2ecf20Sopenharmony_cistatic inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
10588c2ecf20Sopenharmony_ci{
10598c2ecf20Sopenharmony_ci	if (hba->vops)
10608c2ecf20Sopenharmony_ci		return hba->vops->name;
10618c2ecf20Sopenharmony_ci	return "";
10628c2ecf20Sopenharmony_ci}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_init(struct ufs_hba *hba)
10658c2ecf20Sopenharmony_ci{
10668c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->init)
10678c2ecf20Sopenharmony_ci		return hba->vops->init(hba);
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	return 0;
10708c2ecf20Sopenharmony_ci}
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_exit(struct ufs_hba *hba)
10738c2ecf20Sopenharmony_ci{
10748c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->exit)
10758c2ecf20Sopenharmony_ci		return hba->vops->exit(hba);
10768c2ecf20Sopenharmony_ci}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_cistatic inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
10798c2ecf20Sopenharmony_ci{
10808c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->get_ufs_hci_version)
10818c2ecf20Sopenharmony_ci		return hba->vops->get_ufs_hci_version(hba);
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	return ufshcd_readl(hba, REG_UFS_VERSION);
10848c2ecf20Sopenharmony_ci}
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba,
10878c2ecf20Sopenharmony_ci			bool up, enum ufs_notify_change_status status)
10888c2ecf20Sopenharmony_ci{
10898c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->clk_scale_notify)
10908c2ecf20Sopenharmony_ci		return hba->vops->clk_scale_notify(hba, up, status);
10918c2ecf20Sopenharmony_ci	return 0;
10928c2ecf20Sopenharmony_ci}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on,
10958c2ecf20Sopenharmony_ci					enum ufs_notify_change_status status)
10968c2ecf20Sopenharmony_ci{
10978c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->setup_clocks)
10988c2ecf20Sopenharmony_ci		return hba->vops->setup_clocks(hba, on, status);
10998c2ecf20Sopenharmony_ci	return 0;
11008c2ecf20Sopenharmony_ci}
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status)
11038c2ecf20Sopenharmony_ci{
11048c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->setup_regulators)
11058c2ecf20Sopenharmony_ci		return hba->vops->setup_regulators(hba, status);
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	return 0;
11088c2ecf20Sopenharmony_ci}
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba,
11118c2ecf20Sopenharmony_ci						bool status)
11128c2ecf20Sopenharmony_ci{
11138c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->hce_enable_notify)
11148c2ecf20Sopenharmony_ci		return hba->vops->hce_enable_notify(hba, status);
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	return 0;
11178c2ecf20Sopenharmony_ci}
11188c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba,
11198c2ecf20Sopenharmony_ci						bool status)
11208c2ecf20Sopenharmony_ci{
11218c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->link_startup_notify)
11228c2ecf20Sopenharmony_ci		return hba->vops->link_startup_notify(hba, status);
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	return 0;
11258c2ecf20Sopenharmony_ci}
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
11288c2ecf20Sopenharmony_ci				  bool status,
11298c2ecf20Sopenharmony_ci				  struct ufs_pa_layer_attr *dev_max_params,
11308c2ecf20Sopenharmony_ci				  struct ufs_pa_layer_attr *dev_req_params)
11318c2ecf20Sopenharmony_ci{
11328c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->pwr_change_notify)
11338c2ecf20Sopenharmony_ci		return hba->vops->pwr_change_notify(hba, status,
11348c2ecf20Sopenharmony_ci					dev_max_params, dev_req_params);
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	return -ENOTSUPP;
11378c2ecf20Sopenharmony_ci}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_setup_xfer_req(struct ufs_hba *hba, int tag,
11408c2ecf20Sopenharmony_ci					bool is_scsi_cmd)
11418c2ecf20Sopenharmony_ci{
11428c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->setup_xfer_req)
11438c2ecf20Sopenharmony_ci		return hba->vops->setup_xfer_req(hba, tag, is_scsi_cmd);
11448c2ecf20Sopenharmony_ci}
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
11478c2ecf20Sopenharmony_ci					int tag, u8 tm_function)
11488c2ecf20Sopenharmony_ci{
11498c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->setup_task_mgmt)
11508c2ecf20Sopenharmony_ci		return hba->vops->setup_task_mgmt(hba, tag, tm_function);
11518c2ecf20Sopenharmony_ci}
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_hibern8_notify(struct ufs_hba *hba,
11548c2ecf20Sopenharmony_ci					enum uic_cmd_dme cmd,
11558c2ecf20Sopenharmony_ci					enum ufs_notify_change_status status)
11568c2ecf20Sopenharmony_ci{
11578c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->hibern8_notify)
11588c2ecf20Sopenharmony_ci		return hba->vops->hibern8_notify(hba, cmd, status);
11598c2ecf20Sopenharmony_ci}
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba)
11628c2ecf20Sopenharmony_ci{
11638c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->apply_dev_quirks)
11648c2ecf20Sopenharmony_ci		return hba->vops->apply_dev_quirks(hba);
11658c2ecf20Sopenharmony_ci	return 0;
11668c2ecf20Sopenharmony_ci}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_fixup_dev_quirks(struct ufs_hba *hba)
11698c2ecf20Sopenharmony_ci{
11708c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->fixup_dev_quirks)
11718c2ecf20Sopenharmony_ci		hba->vops->fixup_dev_quirks(hba);
11728c2ecf20Sopenharmony_ci}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op)
11758c2ecf20Sopenharmony_ci{
11768c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->suspend)
11778c2ecf20Sopenharmony_ci		return hba->vops->suspend(hba, op);
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	return 0;
11808c2ecf20Sopenharmony_ci}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_cistatic inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op)
11838c2ecf20Sopenharmony_ci{
11848c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->resume)
11858c2ecf20Sopenharmony_ci		return hba->vops->resume(hba, op);
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	return 0;
11888c2ecf20Sopenharmony_ci}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
11918c2ecf20Sopenharmony_ci{
11928c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->dbg_register_dump)
11938c2ecf20Sopenharmony_ci		hba->vops->dbg_register_dump(hba);
11948c2ecf20Sopenharmony_ci}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
11978c2ecf20Sopenharmony_ci{
11988c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->device_reset) {
11998c2ecf20Sopenharmony_ci		int err = hba->vops->device_reset(hba);
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci		if (!err) {
12028c2ecf20Sopenharmony_ci			ufshcd_set_ufs_dev_active(hba);
12038c2ecf20Sopenharmony_ci			if (ufshcd_is_wb_allowed(hba)) {
12048c2ecf20Sopenharmony_ci				hba->wb_enabled = false;
12058c2ecf20Sopenharmony_ci				hba->wb_buf_flush_enabled = false;
12068c2ecf20Sopenharmony_ci			}
12078c2ecf20Sopenharmony_ci		}
12088c2ecf20Sopenharmony_ci		if (err != -EOPNOTSUPP)
12098c2ecf20Sopenharmony_ci			ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err);
12108c2ecf20Sopenharmony_ci	}
12118c2ecf20Sopenharmony_ci}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_cistatic inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba,
12148c2ecf20Sopenharmony_ci						    struct devfreq_dev_profile
12158c2ecf20Sopenharmony_ci						    *profile, void *data)
12168c2ecf20Sopenharmony_ci{
12178c2ecf20Sopenharmony_ci	if (hba->vops && hba->vops->config_scaling_param)
12188c2ecf20Sopenharmony_ci		hba->vops->config_scaling_param(hba, profile, data);
12198c2ecf20Sopenharmony_ci}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ciextern struct ufs_pm_lvl_states ufs_pm_lvl_states[];
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci/*
12248c2ecf20Sopenharmony_ci * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN
12258c2ecf20Sopenharmony_ci * @scsi_lun: scsi LUN id
12268c2ecf20Sopenharmony_ci *
12278c2ecf20Sopenharmony_ci * Returns UPIU LUN id
12288c2ecf20Sopenharmony_ci */
12298c2ecf20Sopenharmony_cistatic inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun)
12308c2ecf20Sopenharmony_ci{
12318c2ecf20Sopenharmony_ci	if (scsi_is_wlun(scsi_lun))
12328c2ecf20Sopenharmony_ci		return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID)
12338c2ecf20Sopenharmony_ci			| UFS_UPIU_WLUN_ID;
12348c2ecf20Sopenharmony_ci	else
12358c2ecf20Sopenharmony_ci		return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID;
12368c2ecf20Sopenharmony_ci}
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ciint ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
12398c2ecf20Sopenharmony_ci		     const char *prefix);
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci#endif /* End of Header */
1242