162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Universal Flash Storage Host controller driver
462306a36Sopenharmony_ci * Copyright (C) 2011-2013 Samsung India Software Operations
562306a36Sopenharmony_ci * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Authors:
862306a36Sopenharmony_ci *	Santosh Yaraganavi <santosh.sy@samsung.com>
962306a36Sopenharmony_ci *	Vinayak Holikatti <h.vinayak@samsung.com>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifndef _UFSHCD_H
1362306a36Sopenharmony_ci#define _UFSHCD_H
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/bitfield.h>
1662306a36Sopenharmony_ci#include <linux/blk-crypto-profile.h>
1762306a36Sopenharmony_ci#include <linux/blk-mq.h>
1862306a36Sopenharmony_ci#include <linux/devfreq.h>
1962306a36Sopenharmony_ci#include <linux/msi.h>
2062306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2162306a36Sopenharmony_ci#include <linux/dma-direction.h>
2262306a36Sopenharmony_ci#include <scsi/scsi_device.h>
2362306a36Sopenharmony_ci#include <scsi/scsi_host.h>
2462306a36Sopenharmony_ci#include <ufs/unipro.h>
2562306a36Sopenharmony_ci#include <ufs/ufs.h>
2662306a36Sopenharmony_ci#include <ufs/ufs_quirks.h>
2762306a36Sopenharmony_ci#include <ufs/ufshci.h>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define UFSHCD "ufshcd"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistruct ufs_hba;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cienum dev_cmd_type {
3462306a36Sopenharmony_ci	DEV_CMD_TYPE_NOP		= 0x0,
3562306a36Sopenharmony_ci	DEV_CMD_TYPE_QUERY		= 0x1,
3662306a36Sopenharmony_ci	DEV_CMD_TYPE_RPMB		= 0x2,
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cienum ufs_event_type {
4062306a36Sopenharmony_ci	/* uic specific errors */
4162306a36Sopenharmony_ci	UFS_EVT_PA_ERR = 0,
4262306a36Sopenharmony_ci	UFS_EVT_DL_ERR,
4362306a36Sopenharmony_ci	UFS_EVT_NL_ERR,
4462306a36Sopenharmony_ci	UFS_EVT_TL_ERR,
4562306a36Sopenharmony_ci	UFS_EVT_DME_ERR,
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* fatal errors */
4862306a36Sopenharmony_ci	UFS_EVT_AUTO_HIBERN8_ERR,
4962306a36Sopenharmony_ci	UFS_EVT_FATAL_ERR,
5062306a36Sopenharmony_ci	UFS_EVT_LINK_STARTUP_FAIL,
5162306a36Sopenharmony_ci	UFS_EVT_RESUME_ERR,
5262306a36Sopenharmony_ci	UFS_EVT_SUSPEND_ERR,
5362306a36Sopenharmony_ci	UFS_EVT_WL_SUSP_ERR,
5462306a36Sopenharmony_ci	UFS_EVT_WL_RES_ERR,
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	/* abnormal events */
5762306a36Sopenharmony_ci	UFS_EVT_DEV_RESET,
5862306a36Sopenharmony_ci	UFS_EVT_HOST_RESET,
5962306a36Sopenharmony_ci	UFS_EVT_ABORT,
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	UFS_EVT_CNT,
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/**
6562306a36Sopenharmony_ci * struct uic_command - UIC command structure
6662306a36Sopenharmony_ci * @command: UIC command
6762306a36Sopenharmony_ci * @argument1: UIC command argument 1
6862306a36Sopenharmony_ci * @argument2: UIC command argument 2
6962306a36Sopenharmony_ci * @argument3: UIC command argument 3
7062306a36Sopenharmony_ci * @cmd_active: Indicate if UIC command is outstanding
7162306a36Sopenharmony_ci * @done: UIC command completion
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistruct uic_command {
7462306a36Sopenharmony_ci	u32 command;
7562306a36Sopenharmony_ci	u32 argument1;
7662306a36Sopenharmony_ci	u32 argument2;
7762306a36Sopenharmony_ci	u32 argument3;
7862306a36Sopenharmony_ci	int cmd_active;
7962306a36Sopenharmony_ci	struct completion done;
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/* Used to differentiate the power management options */
8362306a36Sopenharmony_cienum ufs_pm_op {
8462306a36Sopenharmony_ci	UFS_RUNTIME_PM,
8562306a36Sopenharmony_ci	UFS_SYSTEM_PM,
8662306a36Sopenharmony_ci	UFS_SHUTDOWN_PM,
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/* Host <-> Device UniPro Link state */
9062306a36Sopenharmony_cienum uic_link_state {
9162306a36Sopenharmony_ci	UIC_LINK_OFF_STATE	= 0, /* Link powered down or disabled */
9262306a36Sopenharmony_ci	UIC_LINK_ACTIVE_STATE	= 1, /* Link is in Fast/Slow/Sleep state */
9362306a36Sopenharmony_ci	UIC_LINK_HIBERN8_STATE	= 2, /* Link is in Hibernate state */
9462306a36Sopenharmony_ci	UIC_LINK_BROKEN_STATE	= 3, /* Link is in broken state */
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define ufshcd_is_link_off(hba) ((hba)->uic_link_state == UIC_LINK_OFF_STATE)
9862306a36Sopenharmony_ci#define ufshcd_is_link_active(hba) ((hba)->uic_link_state == \
9962306a36Sopenharmony_ci				    UIC_LINK_ACTIVE_STATE)
10062306a36Sopenharmony_ci#define ufshcd_is_link_hibern8(hba) ((hba)->uic_link_state == \
10162306a36Sopenharmony_ci				    UIC_LINK_HIBERN8_STATE)
10262306a36Sopenharmony_ci#define ufshcd_is_link_broken(hba) ((hba)->uic_link_state == \
10362306a36Sopenharmony_ci				   UIC_LINK_BROKEN_STATE)
10462306a36Sopenharmony_ci#define ufshcd_set_link_off(hba) ((hba)->uic_link_state = UIC_LINK_OFF_STATE)
10562306a36Sopenharmony_ci#define ufshcd_set_link_active(hba) ((hba)->uic_link_state = \
10662306a36Sopenharmony_ci				    UIC_LINK_ACTIVE_STATE)
10762306a36Sopenharmony_ci#define ufshcd_set_link_hibern8(hba) ((hba)->uic_link_state = \
10862306a36Sopenharmony_ci				    UIC_LINK_HIBERN8_STATE)
10962306a36Sopenharmony_ci#define ufshcd_set_link_broken(hba) ((hba)->uic_link_state = \
11062306a36Sopenharmony_ci				    UIC_LINK_BROKEN_STATE)
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#define ufshcd_set_ufs_dev_active(h) \
11362306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE)
11462306a36Sopenharmony_ci#define ufshcd_set_ufs_dev_sleep(h) \
11562306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
11662306a36Sopenharmony_ci#define ufshcd_set_ufs_dev_poweroff(h) \
11762306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
11862306a36Sopenharmony_ci#define ufshcd_set_ufs_dev_deepsleep(h) \
11962306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE)
12062306a36Sopenharmony_ci#define ufshcd_is_ufs_dev_active(h) \
12162306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
12262306a36Sopenharmony_ci#define ufshcd_is_ufs_dev_sleep(h) \
12362306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
12462306a36Sopenharmony_ci#define ufshcd_is_ufs_dev_poweroff(h) \
12562306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
12662306a36Sopenharmony_ci#define ufshcd_is_ufs_dev_deepsleep(h) \
12762306a36Sopenharmony_ci	((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/*
13062306a36Sopenharmony_ci * UFS Power management levels.
13162306a36Sopenharmony_ci * Each level is in increasing order of power savings, except DeepSleep
13262306a36Sopenharmony_ci * which is lower than PowerDown with power on but not PowerDown with
13362306a36Sopenharmony_ci * power off.
13462306a36Sopenharmony_ci */
13562306a36Sopenharmony_cienum ufs_pm_level {
13662306a36Sopenharmony_ci	UFS_PM_LVL_0,
13762306a36Sopenharmony_ci	UFS_PM_LVL_1,
13862306a36Sopenharmony_ci	UFS_PM_LVL_2,
13962306a36Sopenharmony_ci	UFS_PM_LVL_3,
14062306a36Sopenharmony_ci	UFS_PM_LVL_4,
14162306a36Sopenharmony_ci	UFS_PM_LVL_5,
14262306a36Sopenharmony_ci	UFS_PM_LVL_6,
14362306a36Sopenharmony_ci	UFS_PM_LVL_MAX
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistruct ufs_pm_lvl_states {
14762306a36Sopenharmony_ci	enum ufs_dev_pwr_mode dev_state;
14862306a36Sopenharmony_ci	enum uic_link_state link_state;
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci/**
15262306a36Sopenharmony_ci * struct ufshcd_lrb - local reference block
15362306a36Sopenharmony_ci * @utr_descriptor_ptr: UTRD address of the command
15462306a36Sopenharmony_ci * @ucd_req_ptr: UCD address of the command
15562306a36Sopenharmony_ci * @ucd_rsp_ptr: Response UPIU address for this command
15662306a36Sopenharmony_ci * @ucd_prdt_ptr: PRDT address of the command
15762306a36Sopenharmony_ci * @utrd_dma_addr: UTRD dma address for debug
15862306a36Sopenharmony_ci * @ucd_prdt_dma_addr: PRDT dma address for debug
15962306a36Sopenharmony_ci * @ucd_rsp_dma_addr: UPIU response dma address for debug
16062306a36Sopenharmony_ci * @ucd_req_dma_addr: UPIU request dma address for debug
16162306a36Sopenharmony_ci * @cmd: pointer to SCSI command
16262306a36Sopenharmony_ci * @scsi_status: SCSI status of the command
16362306a36Sopenharmony_ci * @command_type: SCSI, UFS, Query.
16462306a36Sopenharmony_ci * @task_tag: Task tag of the command
16562306a36Sopenharmony_ci * @lun: LUN of the command
16662306a36Sopenharmony_ci * @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation)
16762306a36Sopenharmony_ci * @issue_time_stamp: time stamp for debug purposes (CLOCK_MONOTONIC)
16862306a36Sopenharmony_ci * @issue_time_stamp_local_clock: time stamp for debug purposes (local_clock)
16962306a36Sopenharmony_ci * @compl_time_stamp: time stamp for statistics (CLOCK_MONOTONIC)
17062306a36Sopenharmony_ci * @compl_time_stamp_local_clock: time stamp for debug purposes (local_clock)
17162306a36Sopenharmony_ci * @crypto_key_slot: the key slot to use for inline crypto (-1 if none)
17262306a36Sopenharmony_ci * @data_unit_num: the data unit number for the first block for inline crypto
17362306a36Sopenharmony_ci * @req_abort_skip: skip request abort task flag
17462306a36Sopenharmony_ci */
17562306a36Sopenharmony_cistruct ufshcd_lrb {
17662306a36Sopenharmony_ci	struct utp_transfer_req_desc *utr_descriptor_ptr;
17762306a36Sopenharmony_ci	struct utp_upiu_req *ucd_req_ptr;
17862306a36Sopenharmony_ci	struct utp_upiu_rsp *ucd_rsp_ptr;
17962306a36Sopenharmony_ci	struct ufshcd_sg_entry *ucd_prdt_ptr;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	dma_addr_t utrd_dma_addr;
18262306a36Sopenharmony_ci	dma_addr_t ucd_req_dma_addr;
18362306a36Sopenharmony_ci	dma_addr_t ucd_rsp_dma_addr;
18462306a36Sopenharmony_ci	dma_addr_t ucd_prdt_dma_addr;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	struct scsi_cmnd *cmd;
18762306a36Sopenharmony_ci	int scsi_status;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	int command_type;
19062306a36Sopenharmony_ci	int task_tag;
19162306a36Sopenharmony_ci	u8 lun; /* UPIU LUN id field is only 8-bit wide */
19262306a36Sopenharmony_ci	bool intr_cmd;
19362306a36Sopenharmony_ci	ktime_t issue_time_stamp;
19462306a36Sopenharmony_ci	u64 issue_time_stamp_local_clock;
19562306a36Sopenharmony_ci	ktime_t compl_time_stamp;
19662306a36Sopenharmony_ci	u64 compl_time_stamp_local_clock;
19762306a36Sopenharmony_ci#ifdef CONFIG_SCSI_UFS_CRYPTO
19862306a36Sopenharmony_ci	int crypto_key_slot;
19962306a36Sopenharmony_ci	u64 data_unit_num;
20062306a36Sopenharmony_ci#endif
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	bool req_abort_skip;
20362306a36Sopenharmony_ci};
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/**
20662306a36Sopenharmony_ci * struct ufs_query_req - parameters for building a query request
20762306a36Sopenharmony_ci * @query_func: UPIU header query function
20862306a36Sopenharmony_ci * @upiu_req: the query request data
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_cistruct ufs_query_req {
21162306a36Sopenharmony_ci	u8 query_func;
21262306a36Sopenharmony_ci	struct utp_upiu_query upiu_req;
21362306a36Sopenharmony_ci};
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/**
21662306a36Sopenharmony_ci * struct ufs_query_resp - UPIU QUERY
21762306a36Sopenharmony_ci * @response: device response code
21862306a36Sopenharmony_ci * @upiu_res: query response data
21962306a36Sopenharmony_ci */
22062306a36Sopenharmony_cistruct ufs_query_res {
22162306a36Sopenharmony_ci	struct utp_upiu_query upiu_res;
22262306a36Sopenharmony_ci};
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/**
22562306a36Sopenharmony_ci * struct ufs_query - holds relevant data structures for query request
22662306a36Sopenharmony_ci * @request: request upiu and function
22762306a36Sopenharmony_ci * @descriptor: buffer for sending/receiving descriptor
22862306a36Sopenharmony_ci * @response: response upiu and response
22962306a36Sopenharmony_ci */
23062306a36Sopenharmony_cistruct ufs_query {
23162306a36Sopenharmony_ci	struct ufs_query_req request;
23262306a36Sopenharmony_ci	u8 *descriptor;
23362306a36Sopenharmony_ci	struct ufs_query_res response;
23462306a36Sopenharmony_ci};
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/**
23762306a36Sopenharmony_ci * struct ufs_dev_cmd - all assosiated fields with device management commands
23862306a36Sopenharmony_ci * @type: device management command type - Query, NOP OUT
23962306a36Sopenharmony_ci * @lock: lock to allow one command at a time
24062306a36Sopenharmony_ci * @complete: internal commands completion
24162306a36Sopenharmony_ci * @query: Device management query information
24262306a36Sopenharmony_ci */
24362306a36Sopenharmony_cistruct ufs_dev_cmd {
24462306a36Sopenharmony_ci	enum dev_cmd_type type;
24562306a36Sopenharmony_ci	struct mutex lock;
24662306a36Sopenharmony_ci	struct completion *complete;
24762306a36Sopenharmony_ci	struct ufs_query query;
24862306a36Sopenharmony_ci};
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci/**
25162306a36Sopenharmony_ci * struct ufs_clk_info - UFS clock related info
25262306a36Sopenharmony_ci * @list: list headed by hba->clk_list_head
25362306a36Sopenharmony_ci * @clk: clock node
25462306a36Sopenharmony_ci * @name: clock name
25562306a36Sopenharmony_ci * @max_freq: maximum frequency supported by the clock
25662306a36Sopenharmony_ci * @min_freq: min frequency that can be used for clock scaling
25762306a36Sopenharmony_ci * @curr_freq: indicates the current frequency that it is set to
25862306a36Sopenharmony_ci * @keep_link_active: indicates that the clk should not be disabled if
25962306a36Sopenharmony_ci *		      link is active
26062306a36Sopenharmony_ci * @enabled: variable to check against multiple enable/disable
26162306a36Sopenharmony_ci */
26262306a36Sopenharmony_cistruct ufs_clk_info {
26362306a36Sopenharmony_ci	struct list_head list;
26462306a36Sopenharmony_ci	struct clk *clk;
26562306a36Sopenharmony_ci	const char *name;
26662306a36Sopenharmony_ci	u32 max_freq;
26762306a36Sopenharmony_ci	u32 min_freq;
26862306a36Sopenharmony_ci	u32 curr_freq;
26962306a36Sopenharmony_ci	bool keep_link_active;
27062306a36Sopenharmony_ci	bool enabled;
27162306a36Sopenharmony_ci};
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cienum ufs_notify_change_status {
27462306a36Sopenharmony_ci	PRE_CHANGE,
27562306a36Sopenharmony_ci	POST_CHANGE,
27662306a36Sopenharmony_ci};
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistruct ufs_pa_layer_attr {
27962306a36Sopenharmony_ci	u32 gear_rx;
28062306a36Sopenharmony_ci	u32 gear_tx;
28162306a36Sopenharmony_ci	u32 lane_rx;
28262306a36Sopenharmony_ci	u32 lane_tx;
28362306a36Sopenharmony_ci	u32 pwr_rx;
28462306a36Sopenharmony_ci	u32 pwr_tx;
28562306a36Sopenharmony_ci	u32 hs_rate;
28662306a36Sopenharmony_ci};
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistruct ufs_pwr_mode_info {
28962306a36Sopenharmony_ci	bool is_valid;
29062306a36Sopenharmony_ci	struct ufs_pa_layer_attr info;
29162306a36Sopenharmony_ci};
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci/**
29462306a36Sopenharmony_ci * struct ufs_hba_variant_ops - variant specific callbacks
29562306a36Sopenharmony_ci * @name: variant name
29662306a36Sopenharmony_ci * @init: called when the driver is initialized
29762306a36Sopenharmony_ci * @exit: called to cleanup everything done in init
29862306a36Sopenharmony_ci * @get_ufs_hci_version: called to get UFS HCI version
29962306a36Sopenharmony_ci * @clk_scale_notify: notifies that clks are scaled up/down
30062306a36Sopenharmony_ci * @setup_clocks: called before touching any of the controller registers
30162306a36Sopenharmony_ci * @hce_enable_notify: called before and after HCE enable bit is set to allow
30262306a36Sopenharmony_ci *                     variant specific Uni-Pro initialization.
30362306a36Sopenharmony_ci * @link_startup_notify: called before and after Link startup is carried out
30462306a36Sopenharmony_ci *                       to allow variant specific Uni-Pro initialization.
30562306a36Sopenharmony_ci * @pwr_change_notify: called before and after a power mode change
30662306a36Sopenharmony_ci *			is carried out to allow vendor spesific capabilities
30762306a36Sopenharmony_ci *			to be set.
30862306a36Sopenharmony_ci * @setup_xfer_req: called before any transfer request is issued
30962306a36Sopenharmony_ci *                  to set some things
31062306a36Sopenharmony_ci * @setup_task_mgmt: called before any task management request is issued
31162306a36Sopenharmony_ci *                  to set some things
31262306a36Sopenharmony_ci * @hibern8_notify: called around hibern8 enter/exit
31362306a36Sopenharmony_ci * @apply_dev_quirks: called to apply device specific quirks
31462306a36Sopenharmony_ci * @fixup_dev_quirks: called to modify device specific quirks
31562306a36Sopenharmony_ci * @suspend: called during host controller PM callback
31662306a36Sopenharmony_ci * @resume: called during host controller PM callback
31762306a36Sopenharmony_ci * @dbg_register_dump: used to dump controller debug information
31862306a36Sopenharmony_ci * @phy_initialization: used to initialize phys
31962306a36Sopenharmony_ci * @device_reset: called to issue a reset pulse on the UFS device
32062306a36Sopenharmony_ci * @config_scaling_param: called to configure clock scaling parameters
32162306a36Sopenharmony_ci * @program_key: program or evict an inline encryption key
32262306a36Sopenharmony_ci * @event_notify: called to notify important events
32362306a36Sopenharmony_ci * @reinit_notify: called to notify reinit of UFSHCD during max gear switch
32462306a36Sopenharmony_ci * @mcq_config_resource: called to configure MCQ platform resources
32562306a36Sopenharmony_ci * @get_hba_mac: called to get vendor specific mac value, mandatory for mcq mode
32662306a36Sopenharmony_ci * @op_runtime_config: called to config Operation and runtime regs Pointers
32762306a36Sopenharmony_ci * @get_outstanding_cqs: called to get outstanding completion queues
32862306a36Sopenharmony_ci * @config_esi: called to config Event Specific Interrupt
32962306a36Sopenharmony_ci */
33062306a36Sopenharmony_cistruct ufs_hba_variant_ops {
33162306a36Sopenharmony_ci	const char *name;
33262306a36Sopenharmony_ci	int	(*init)(struct ufs_hba *);
33362306a36Sopenharmony_ci	void    (*exit)(struct ufs_hba *);
33462306a36Sopenharmony_ci	u32	(*get_ufs_hci_version)(struct ufs_hba *);
33562306a36Sopenharmony_ci	int	(*clk_scale_notify)(struct ufs_hba *, bool,
33662306a36Sopenharmony_ci				    enum ufs_notify_change_status);
33762306a36Sopenharmony_ci	int	(*setup_clocks)(struct ufs_hba *, bool,
33862306a36Sopenharmony_ci				enum ufs_notify_change_status);
33962306a36Sopenharmony_ci	int	(*hce_enable_notify)(struct ufs_hba *,
34062306a36Sopenharmony_ci				     enum ufs_notify_change_status);
34162306a36Sopenharmony_ci	int	(*link_startup_notify)(struct ufs_hba *,
34262306a36Sopenharmony_ci				       enum ufs_notify_change_status);
34362306a36Sopenharmony_ci	int	(*pwr_change_notify)(struct ufs_hba *,
34462306a36Sopenharmony_ci					enum ufs_notify_change_status status,
34562306a36Sopenharmony_ci					struct ufs_pa_layer_attr *,
34662306a36Sopenharmony_ci					struct ufs_pa_layer_attr *);
34762306a36Sopenharmony_ci	void	(*setup_xfer_req)(struct ufs_hba *hba, int tag,
34862306a36Sopenharmony_ci				  bool is_scsi_cmd);
34962306a36Sopenharmony_ci	void	(*setup_task_mgmt)(struct ufs_hba *, int, u8);
35062306a36Sopenharmony_ci	void    (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme,
35162306a36Sopenharmony_ci					enum ufs_notify_change_status);
35262306a36Sopenharmony_ci	int	(*apply_dev_quirks)(struct ufs_hba *hba);
35362306a36Sopenharmony_ci	void	(*fixup_dev_quirks)(struct ufs_hba *hba);
35462306a36Sopenharmony_ci	int     (*suspend)(struct ufs_hba *, enum ufs_pm_op,
35562306a36Sopenharmony_ci					enum ufs_notify_change_status);
35662306a36Sopenharmony_ci	int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
35762306a36Sopenharmony_ci	void	(*dbg_register_dump)(struct ufs_hba *hba);
35862306a36Sopenharmony_ci	int	(*phy_initialization)(struct ufs_hba *);
35962306a36Sopenharmony_ci	int	(*device_reset)(struct ufs_hba *hba);
36062306a36Sopenharmony_ci	void	(*config_scaling_param)(struct ufs_hba *hba,
36162306a36Sopenharmony_ci				struct devfreq_dev_profile *profile,
36262306a36Sopenharmony_ci				struct devfreq_simple_ondemand_data *data);
36362306a36Sopenharmony_ci	int	(*program_key)(struct ufs_hba *hba,
36462306a36Sopenharmony_ci			       const union ufs_crypto_cfg_entry *cfg, int slot);
36562306a36Sopenharmony_ci	void	(*event_notify)(struct ufs_hba *hba,
36662306a36Sopenharmony_ci				enum ufs_event_type evt, void *data);
36762306a36Sopenharmony_ci	void	(*reinit_notify)(struct ufs_hba *);
36862306a36Sopenharmony_ci	int	(*mcq_config_resource)(struct ufs_hba *hba);
36962306a36Sopenharmony_ci	int	(*get_hba_mac)(struct ufs_hba *hba);
37062306a36Sopenharmony_ci	int	(*op_runtime_config)(struct ufs_hba *hba);
37162306a36Sopenharmony_ci	int	(*get_outstanding_cqs)(struct ufs_hba *hba,
37262306a36Sopenharmony_ci				       unsigned long *ocqs);
37362306a36Sopenharmony_ci	int	(*config_esi)(struct ufs_hba *hba);
37462306a36Sopenharmony_ci};
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci/* clock gating state  */
37762306a36Sopenharmony_cienum clk_gating_state {
37862306a36Sopenharmony_ci	CLKS_OFF,
37962306a36Sopenharmony_ci	CLKS_ON,
38062306a36Sopenharmony_ci	REQ_CLKS_OFF,
38162306a36Sopenharmony_ci	REQ_CLKS_ON,
38262306a36Sopenharmony_ci};
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci/**
38562306a36Sopenharmony_ci * struct ufs_clk_gating - UFS clock gating related info
38662306a36Sopenharmony_ci * @gate_work: worker to turn off clocks after some delay as specified in
38762306a36Sopenharmony_ci * delay_ms
38862306a36Sopenharmony_ci * @ungate_work: worker to turn on clocks that will be used in case of
38962306a36Sopenharmony_ci * interrupt context
39062306a36Sopenharmony_ci * @state: the current clocks state
39162306a36Sopenharmony_ci * @delay_ms: gating delay in ms
39262306a36Sopenharmony_ci * @is_suspended: clk gating is suspended when set to 1 which can be used
39362306a36Sopenharmony_ci * during suspend/resume
39462306a36Sopenharmony_ci * @delay_attr: sysfs attribute to control delay_attr
39562306a36Sopenharmony_ci * @enable_attr: sysfs attribute to enable/disable clock gating
39662306a36Sopenharmony_ci * @is_enabled: Indicates the current status of clock gating
39762306a36Sopenharmony_ci * @is_initialized: Indicates whether clock gating is initialized or not
39862306a36Sopenharmony_ci * @active_reqs: number of requests that are pending and should be waited for
39962306a36Sopenharmony_ci * completion before gating clocks.
40062306a36Sopenharmony_ci * @clk_gating_workq: workqueue for clock gating work.
40162306a36Sopenharmony_ci */
40262306a36Sopenharmony_cistruct ufs_clk_gating {
40362306a36Sopenharmony_ci	struct delayed_work gate_work;
40462306a36Sopenharmony_ci	struct work_struct ungate_work;
40562306a36Sopenharmony_ci	enum clk_gating_state state;
40662306a36Sopenharmony_ci	unsigned long delay_ms;
40762306a36Sopenharmony_ci	bool is_suspended;
40862306a36Sopenharmony_ci	struct device_attribute delay_attr;
40962306a36Sopenharmony_ci	struct device_attribute enable_attr;
41062306a36Sopenharmony_ci	bool is_enabled;
41162306a36Sopenharmony_ci	bool is_initialized;
41262306a36Sopenharmony_ci	int active_reqs;
41362306a36Sopenharmony_ci	struct workqueue_struct *clk_gating_workq;
41462306a36Sopenharmony_ci};
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci/**
41762306a36Sopenharmony_ci * struct ufs_clk_scaling - UFS clock scaling related data
41862306a36Sopenharmony_ci * @active_reqs: number of requests that are pending. If this is zero when
41962306a36Sopenharmony_ci * devfreq ->target() function is called then schedule "suspend_work" to
42062306a36Sopenharmony_ci * suspend devfreq.
42162306a36Sopenharmony_ci * @tot_busy_t: Total busy time in current polling window
42262306a36Sopenharmony_ci * @window_start_t: Start time (in jiffies) of the current polling window
42362306a36Sopenharmony_ci * @busy_start_t: Start time of current busy period
42462306a36Sopenharmony_ci * @enable_attr: sysfs attribute to enable/disable clock scaling
42562306a36Sopenharmony_ci * @saved_pwr_info: UFS power mode may also be changed during scaling and this
42662306a36Sopenharmony_ci * one keeps track of previous power mode.
42762306a36Sopenharmony_ci * @workq: workqueue to schedule devfreq suspend/resume work
42862306a36Sopenharmony_ci * @suspend_work: worker to suspend devfreq
42962306a36Sopenharmony_ci * @resume_work: worker to resume devfreq
43062306a36Sopenharmony_ci * @min_gear: lowest HS gear to scale down to
43162306a36Sopenharmony_ci * @is_enabled: tracks if scaling is currently enabled or not, controlled by
43262306a36Sopenharmony_ci *		clkscale_enable sysfs node
43362306a36Sopenharmony_ci * @is_allowed: tracks if scaling is currently allowed or not, used to block
43462306a36Sopenharmony_ci *		clock scaling which is not invoked from devfreq governor
43562306a36Sopenharmony_ci * @is_initialized: Indicates whether clock scaling is initialized or not
43662306a36Sopenharmony_ci * @is_busy_started: tracks if busy period has started or not
43762306a36Sopenharmony_ci * @is_suspended: tracks if devfreq is suspended or not
43862306a36Sopenharmony_ci */
43962306a36Sopenharmony_cistruct ufs_clk_scaling {
44062306a36Sopenharmony_ci	int active_reqs;
44162306a36Sopenharmony_ci	unsigned long tot_busy_t;
44262306a36Sopenharmony_ci	ktime_t window_start_t;
44362306a36Sopenharmony_ci	ktime_t busy_start_t;
44462306a36Sopenharmony_ci	struct device_attribute enable_attr;
44562306a36Sopenharmony_ci	struct ufs_pa_layer_attr saved_pwr_info;
44662306a36Sopenharmony_ci	struct workqueue_struct *workq;
44762306a36Sopenharmony_ci	struct work_struct suspend_work;
44862306a36Sopenharmony_ci	struct work_struct resume_work;
44962306a36Sopenharmony_ci	u32 min_gear;
45062306a36Sopenharmony_ci	bool is_enabled;
45162306a36Sopenharmony_ci	bool is_allowed;
45262306a36Sopenharmony_ci	bool is_initialized;
45362306a36Sopenharmony_ci	bool is_busy_started;
45462306a36Sopenharmony_ci	bool is_suspended;
45562306a36Sopenharmony_ci};
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci#define UFS_EVENT_HIST_LENGTH 8
45862306a36Sopenharmony_ci/**
45962306a36Sopenharmony_ci * struct ufs_event_hist - keeps history of errors
46062306a36Sopenharmony_ci * @pos: index to indicate cyclic buffer position
46162306a36Sopenharmony_ci * @val: cyclic buffer for registers value
46262306a36Sopenharmony_ci * @tstamp: cyclic buffer for time stamp
46362306a36Sopenharmony_ci * @cnt: error counter
46462306a36Sopenharmony_ci */
46562306a36Sopenharmony_cistruct ufs_event_hist {
46662306a36Sopenharmony_ci	int pos;
46762306a36Sopenharmony_ci	u32 val[UFS_EVENT_HIST_LENGTH];
46862306a36Sopenharmony_ci	u64 tstamp[UFS_EVENT_HIST_LENGTH];
46962306a36Sopenharmony_ci	unsigned long long cnt;
47062306a36Sopenharmony_ci};
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci/**
47362306a36Sopenharmony_ci * struct ufs_stats - keeps usage/err statistics
47462306a36Sopenharmony_ci * @last_intr_status: record the last interrupt status.
47562306a36Sopenharmony_ci * @last_intr_ts: record the last interrupt timestamp.
47662306a36Sopenharmony_ci * @hibern8_exit_cnt: Counter to keep track of number of exits,
47762306a36Sopenharmony_ci *		reset this after link-startup.
47862306a36Sopenharmony_ci * @last_hibern8_exit_tstamp: Set time after the hibern8 exit.
47962306a36Sopenharmony_ci *		Clear after the first successful command completion.
48062306a36Sopenharmony_ci * @event: array with event history.
48162306a36Sopenharmony_ci */
48262306a36Sopenharmony_cistruct ufs_stats {
48362306a36Sopenharmony_ci	u32 last_intr_status;
48462306a36Sopenharmony_ci	u64 last_intr_ts;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	u32 hibern8_exit_cnt;
48762306a36Sopenharmony_ci	u64 last_hibern8_exit_tstamp;
48862306a36Sopenharmony_ci	struct ufs_event_hist event[UFS_EVT_CNT];
48962306a36Sopenharmony_ci};
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci/**
49262306a36Sopenharmony_ci * enum ufshcd_state - UFS host controller state
49362306a36Sopenharmony_ci * @UFSHCD_STATE_RESET: Link is not operational. Postpone SCSI command
49462306a36Sopenharmony_ci *	processing.
49562306a36Sopenharmony_ci * @UFSHCD_STATE_OPERATIONAL: The host controller is operational and can process
49662306a36Sopenharmony_ci *	SCSI commands.
49762306a36Sopenharmony_ci * @UFSHCD_STATE_EH_SCHEDULED_NON_FATAL: The error handler has been scheduled.
49862306a36Sopenharmony_ci *	SCSI commands may be submitted to the controller.
49962306a36Sopenharmony_ci * @UFSHCD_STATE_EH_SCHEDULED_FATAL: The error handler has been scheduled. Fail
50062306a36Sopenharmony_ci *	newly submitted SCSI commands with error code DID_BAD_TARGET.
50162306a36Sopenharmony_ci * @UFSHCD_STATE_ERROR: An unrecoverable error occurred, e.g. link recovery
50262306a36Sopenharmony_ci *	failed. Fail all SCSI commands with error code DID_ERROR.
50362306a36Sopenharmony_ci */
50462306a36Sopenharmony_cienum ufshcd_state {
50562306a36Sopenharmony_ci	UFSHCD_STATE_RESET,
50662306a36Sopenharmony_ci	UFSHCD_STATE_OPERATIONAL,
50762306a36Sopenharmony_ci	UFSHCD_STATE_EH_SCHEDULED_NON_FATAL,
50862306a36Sopenharmony_ci	UFSHCD_STATE_EH_SCHEDULED_FATAL,
50962306a36Sopenharmony_ci	UFSHCD_STATE_ERROR,
51062306a36Sopenharmony_ci};
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cienum ufshcd_quirks {
51362306a36Sopenharmony_ci	/* Interrupt aggregation support is broken */
51462306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_INTR_AGGR			= 1 << 0,
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	/*
51762306a36Sopenharmony_ci	 * delay before each dme command is required as the unipro
51862306a36Sopenharmony_ci	 * layer has shown instabilities
51962306a36Sopenharmony_ci	 */
52062306a36Sopenharmony_ci	UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS		= 1 << 1,
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	/*
52362306a36Sopenharmony_ci	 * If UFS host controller is having issue in processing LCC (Line
52462306a36Sopenharmony_ci	 * Control Command) coming from device then enable this quirk.
52562306a36Sopenharmony_ci	 * When this quirk is enabled, host controller driver should disable
52662306a36Sopenharmony_ci	 * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
52762306a36Sopenharmony_ci	 * attribute of device to 0).
52862306a36Sopenharmony_ci	 */
52962306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_LCC				= 1 << 2,
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	/*
53262306a36Sopenharmony_ci	 * The attribute PA_RXHSUNTERMCAP specifies whether or not the
53362306a36Sopenharmony_ci	 * inbound Link supports unterminated line in HS mode. Setting this
53462306a36Sopenharmony_ci	 * attribute to 1 fixes moving to HS gear.
53562306a36Sopenharmony_ci	 */
53662306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP		= 1 << 3,
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	/*
53962306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller only allows
54062306a36Sopenharmony_ci	 * accessing the peer dme attributes in AUTO mode (FAST AUTO or
54162306a36Sopenharmony_ci	 * SLOW AUTO).
54262306a36Sopenharmony_ci	 */
54362306a36Sopenharmony_ci	UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE		= 1 << 4,
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	/*
54662306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller doesn't
54762306a36Sopenharmony_ci	 * advertise the correct version in UFS_VER register. If this quirk
54862306a36Sopenharmony_ci	 * is enabled, standard UFS host driver will call the vendor specific
54962306a36Sopenharmony_ci	 * ops (get_ufs_hci_version) to get the correct version.
55062306a36Sopenharmony_ci	 */
55162306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION		= 1 << 5,
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	/*
55462306a36Sopenharmony_ci	 * Clear handling for transfer/task request list is just opposite.
55562306a36Sopenharmony_ci	 */
55662306a36Sopenharmony_ci	UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR		= 1 << 6,
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	/*
55962306a36Sopenharmony_ci	 * This quirk needs to be enabled if host controller doesn't allow
56062306a36Sopenharmony_ci	 * that the interrupt aggregation timer and counter are reset by s/w.
56162306a36Sopenharmony_ci	 */
56262306a36Sopenharmony_ci	UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR		= 1 << 7,
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	/*
56562306a36Sopenharmony_ci	 * This quirks needs to be enabled if host controller cannot be
56662306a36Sopenharmony_ci	 * enabled via HCE register.
56762306a36Sopenharmony_ci	 */
56862306a36Sopenharmony_ci	UFSHCI_QUIRK_BROKEN_HCE				= 1 << 8,
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	/*
57162306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller regards
57262306a36Sopenharmony_ci	 * resolution of the values of PRDTO and PRDTL in UTRD as byte.
57362306a36Sopenharmony_ci	 */
57462306a36Sopenharmony_ci	UFSHCD_QUIRK_PRDT_BYTE_GRAN			= 1 << 9,
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	/*
57762306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller reports
57862306a36Sopenharmony_ci	 * OCS FATAL ERROR with device error through sense data
57962306a36Sopenharmony_ci	 */
58062306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR		= 1 << 10,
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	/*
58362306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller has
58462306a36Sopenharmony_ci	 * auto-hibernate capability but it doesn't work.
58562306a36Sopenharmony_ci	 */
58662306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8		= 1 << 11,
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	/*
58962306a36Sopenharmony_ci	 * This quirk needs to disable manual flush for write booster
59062306a36Sopenharmony_ci	 */
59162306a36Sopenharmony_ci	UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL		= 1 << 12,
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	/*
59462306a36Sopenharmony_ci	 * This quirk needs to disable unipro timeout values
59562306a36Sopenharmony_ci	 * before power mode change
59662306a36Sopenharmony_ci	 */
59762306a36Sopenharmony_ci	UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13,
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/*
60062306a36Sopenharmony_ci	 * Align DMA SG entries on a 4 KiB boundary.
60162306a36Sopenharmony_ci	 */
60262306a36Sopenharmony_ci	UFSHCD_QUIRK_4KB_DMA_ALIGNMENT			= 1 << 14,
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	/*
60562306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller does not
60662306a36Sopenharmony_ci	 * support UIC command
60762306a36Sopenharmony_ci	 */
60862306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_UIC_CMD			= 1 << 15,
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	/*
61162306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller cannot
61262306a36Sopenharmony_ci	 * support physical host configuration.
61362306a36Sopenharmony_ci	 */
61462306a36Sopenharmony_ci	UFSHCD_QUIRK_SKIP_PH_CONFIGURATION		= 1 << 16,
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	/*
61762306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller has
61862306a36Sopenharmony_ci	 * 64-bit addressing supported capability but it doesn't work.
61962306a36Sopenharmony_ci	 */
62062306a36Sopenharmony_ci	UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS		= 1 << 17,
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	/*
62362306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller has
62462306a36Sopenharmony_ci	 * auto-hibernate capability but it's FASTAUTO only.
62562306a36Sopenharmony_ci	 */
62662306a36Sopenharmony_ci	UFSHCD_QUIRK_HIBERN_FASTAUTO			= 1 << 18,
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	/*
62962306a36Sopenharmony_ci	 * This quirk needs to be enabled if the host controller needs
63062306a36Sopenharmony_ci	 * to reinit the device after switching to maximum gear.
63162306a36Sopenharmony_ci	 */
63262306a36Sopenharmony_ci	UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH       = 1 << 19,
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	/*
63562306a36Sopenharmony_ci	 * Some host raises interrupt (per queue) in addition to
63662306a36Sopenharmony_ci	 * CQES (traditional) when ESI is disabled.
63762306a36Sopenharmony_ci	 * Enable this quirk will disable CQES and use per queue interrupt.
63862306a36Sopenharmony_ci	 */
63962306a36Sopenharmony_ci	UFSHCD_QUIRK_MCQ_BROKEN_INTR			= 1 << 20,
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	/*
64262306a36Sopenharmony_ci	 * Some host does not implement SQ Run Time Command (SQRTC) register
64362306a36Sopenharmony_ci	 * thus need this quirk to skip related flow.
64462306a36Sopenharmony_ci	 */
64562306a36Sopenharmony_ci	UFSHCD_QUIRK_MCQ_BROKEN_RTC			= 1 << 21,
64662306a36Sopenharmony_ci};
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_cienum ufshcd_caps {
64962306a36Sopenharmony_ci	/* Allow dynamic clk gating */
65062306a36Sopenharmony_ci	UFSHCD_CAP_CLK_GATING				= 1 << 0,
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	/* Allow hiberb8 with clk gating */
65362306a36Sopenharmony_ci	UFSHCD_CAP_HIBERN8_WITH_CLK_GATING		= 1 << 1,
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	/* Allow dynamic clk scaling */
65662306a36Sopenharmony_ci	UFSHCD_CAP_CLK_SCALING				= 1 << 2,
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	/* Allow auto bkops to enabled during runtime suspend */
65962306a36Sopenharmony_ci	UFSHCD_CAP_AUTO_BKOPS_SUSPEND			= 1 << 3,
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	/*
66262306a36Sopenharmony_ci	 * This capability allows host controller driver to use the UFS HCI's
66362306a36Sopenharmony_ci	 * interrupt aggregation capability.
66462306a36Sopenharmony_ci	 * CAUTION: Enabling this might reduce overall UFS throughput.
66562306a36Sopenharmony_ci	 */
66662306a36Sopenharmony_ci	UFSHCD_CAP_INTR_AGGR				= 1 << 4,
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	/*
66962306a36Sopenharmony_ci	 * This capability allows the device auto-bkops to be always enabled
67062306a36Sopenharmony_ci	 * except during suspend (both runtime and suspend).
67162306a36Sopenharmony_ci	 * Enabling this capability means that device will always be allowed
67262306a36Sopenharmony_ci	 * to do background operation when it's active but it might degrade
67362306a36Sopenharmony_ci	 * the performance of ongoing read/write operations.
67462306a36Sopenharmony_ci	 */
67562306a36Sopenharmony_ci	UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND = 1 << 5,
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	/*
67862306a36Sopenharmony_ci	 * This capability allows host controller driver to automatically
67962306a36Sopenharmony_ci	 * enable runtime power management by itself instead of waiting
68062306a36Sopenharmony_ci	 * for userspace to control the power management.
68162306a36Sopenharmony_ci	 */
68262306a36Sopenharmony_ci	UFSHCD_CAP_RPM_AUTOSUSPEND			= 1 << 6,
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	/*
68562306a36Sopenharmony_ci	 * This capability allows the host controller driver to turn-on
68662306a36Sopenharmony_ci	 * WriteBooster, if the underlying device supports it and is
68762306a36Sopenharmony_ci	 * provisioned to be used. This would increase the write performance.
68862306a36Sopenharmony_ci	 */
68962306a36Sopenharmony_ci	UFSHCD_CAP_WB_EN				= 1 << 7,
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	/*
69262306a36Sopenharmony_ci	 * This capability allows the host controller driver to use the
69362306a36Sopenharmony_ci	 * inline crypto engine, if it is present
69462306a36Sopenharmony_ci	 */
69562306a36Sopenharmony_ci	UFSHCD_CAP_CRYPTO				= 1 << 8,
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	/*
69862306a36Sopenharmony_ci	 * This capability allows the controller regulators to be put into
69962306a36Sopenharmony_ci	 * lpm mode aggressively during clock gating.
70062306a36Sopenharmony_ci	 * This would increase power savings.
70162306a36Sopenharmony_ci	 */
70262306a36Sopenharmony_ci	UFSHCD_CAP_AGGR_POWER_COLLAPSE			= 1 << 9,
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	/*
70562306a36Sopenharmony_ci	 * This capability allows the host controller driver to use DeepSleep,
70662306a36Sopenharmony_ci	 * if it is supported by the UFS device. The host controller driver must
70762306a36Sopenharmony_ci	 * support device hardware reset via the hba->device_reset() callback,
70862306a36Sopenharmony_ci	 * in order to exit DeepSleep state.
70962306a36Sopenharmony_ci	 */
71062306a36Sopenharmony_ci	UFSHCD_CAP_DEEPSLEEP				= 1 << 10,
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	/*
71362306a36Sopenharmony_ci	 * This capability allows the host controller driver to use temperature
71462306a36Sopenharmony_ci	 * notification if it is supported by the UFS device.
71562306a36Sopenharmony_ci	 */
71662306a36Sopenharmony_ci	UFSHCD_CAP_TEMP_NOTIF				= 1 << 11,
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	/*
71962306a36Sopenharmony_ci	 * Enable WriteBooster when scaling up the clock and disable
72062306a36Sopenharmony_ci	 * WriteBooster when scaling the clock down.
72162306a36Sopenharmony_ci	 */
72262306a36Sopenharmony_ci	UFSHCD_CAP_WB_WITH_CLK_SCALING			= 1 << 12,
72362306a36Sopenharmony_ci};
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_cistruct ufs_hba_variant_params {
72662306a36Sopenharmony_ci	struct devfreq_dev_profile devfreq_profile;
72762306a36Sopenharmony_ci	struct devfreq_simple_ondemand_data ondemand_data;
72862306a36Sopenharmony_ci	u16 hba_enable_delay_us;
72962306a36Sopenharmony_ci	u32 wb_flush_threshold;
73062306a36Sopenharmony_ci};
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_cistruct ufs_hba_monitor {
73362306a36Sopenharmony_ci	unsigned long chunk_size;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	unsigned long nr_sec_rw[2];
73662306a36Sopenharmony_ci	ktime_t total_busy[2];
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	unsigned long nr_req[2];
73962306a36Sopenharmony_ci	/* latencies*/
74062306a36Sopenharmony_ci	ktime_t lat_sum[2];
74162306a36Sopenharmony_ci	ktime_t lat_max[2];
74262306a36Sopenharmony_ci	ktime_t lat_min[2];
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	u32 nr_queued[2];
74562306a36Sopenharmony_ci	ktime_t busy_start_ts[2];
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	ktime_t enabled_ts;
74862306a36Sopenharmony_ci	bool enabled;
74962306a36Sopenharmony_ci};
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci/**
75262306a36Sopenharmony_ci * struct ufshcd_res_info_t - MCQ related resource regions
75362306a36Sopenharmony_ci *
75462306a36Sopenharmony_ci * @name: resource name
75562306a36Sopenharmony_ci * @resource: pointer to resource region
75662306a36Sopenharmony_ci * @base: register base address
75762306a36Sopenharmony_ci */
75862306a36Sopenharmony_cistruct ufshcd_res_info {
75962306a36Sopenharmony_ci	const char *name;
76062306a36Sopenharmony_ci	struct resource *resource;
76162306a36Sopenharmony_ci	void __iomem *base;
76262306a36Sopenharmony_ci};
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_cienum ufshcd_res {
76562306a36Sopenharmony_ci	RES_UFS,
76662306a36Sopenharmony_ci	RES_MCQ,
76762306a36Sopenharmony_ci	RES_MCQ_SQD,
76862306a36Sopenharmony_ci	RES_MCQ_SQIS,
76962306a36Sopenharmony_ci	RES_MCQ_CQD,
77062306a36Sopenharmony_ci	RES_MCQ_CQIS,
77162306a36Sopenharmony_ci	RES_MCQ_VS,
77262306a36Sopenharmony_ci	RES_MAX,
77362306a36Sopenharmony_ci};
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci/**
77662306a36Sopenharmony_ci * struct ufshcd_mcq_opr_info_t - Operation and Runtime registers
77762306a36Sopenharmony_ci *
77862306a36Sopenharmony_ci * @offset: Doorbell Address Offset
77962306a36Sopenharmony_ci * @stride: Steps proportional to queue [0...31]
78062306a36Sopenharmony_ci * @base: base address
78162306a36Sopenharmony_ci */
78262306a36Sopenharmony_cistruct ufshcd_mcq_opr_info_t {
78362306a36Sopenharmony_ci	unsigned long offset;
78462306a36Sopenharmony_ci	unsigned long stride;
78562306a36Sopenharmony_ci	void __iomem *base;
78662306a36Sopenharmony_ci};
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_cienum ufshcd_mcq_opr {
78962306a36Sopenharmony_ci	OPR_SQD,
79062306a36Sopenharmony_ci	OPR_SQIS,
79162306a36Sopenharmony_ci	OPR_CQD,
79262306a36Sopenharmony_ci	OPR_CQIS,
79362306a36Sopenharmony_ci	OPR_MAX,
79462306a36Sopenharmony_ci};
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci/**
79762306a36Sopenharmony_ci * struct ufs_hba - per adapter private structure
79862306a36Sopenharmony_ci * @mmio_base: UFSHCI base register address
79962306a36Sopenharmony_ci * @ucdl_base_addr: UFS Command Descriptor base address
80062306a36Sopenharmony_ci * @utrdl_base_addr: UTP Transfer Request Descriptor base address
80162306a36Sopenharmony_ci * @utmrdl_base_addr: UTP Task Management Descriptor base address
80262306a36Sopenharmony_ci * @ucdl_dma_addr: UFS Command Descriptor DMA address
80362306a36Sopenharmony_ci * @utrdl_dma_addr: UTRDL DMA address
80462306a36Sopenharmony_ci * @utmrdl_dma_addr: UTMRDL DMA address
80562306a36Sopenharmony_ci * @host: Scsi_Host instance of the driver
80662306a36Sopenharmony_ci * @dev: device handle
80762306a36Sopenharmony_ci * @ufs_device_wlun: WLUN that controls the entire UFS device.
80862306a36Sopenharmony_ci * @hwmon_device: device instance registered with the hwmon core.
80962306a36Sopenharmony_ci * @curr_dev_pwr_mode: active UFS device power mode.
81062306a36Sopenharmony_ci * @uic_link_state: active state of the link to the UFS device.
81162306a36Sopenharmony_ci * @rpm_lvl: desired UFS power management level during runtime PM.
81262306a36Sopenharmony_ci * @spm_lvl: desired UFS power management level during system PM.
81362306a36Sopenharmony_ci * @pm_op_in_progress: whether or not a PM operation is in progress.
81462306a36Sopenharmony_ci * @ahit: value of Auto-Hibernate Idle Timer register.
81562306a36Sopenharmony_ci * @lrb: local reference block
81662306a36Sopenharmony_ci * @outstanding_tasks: Bits representing outstanding task requests
81762306a36Sopenharmony_ci * @outstanding_lock: Protects @outstanding_reqs.
81862306a36Sopenharmony_ci * @outstanding_reqs: Bits representing outstanding transfer requests
81962306a36Sopenharmony_ci * @capabilities: UFS Controller Capabilities
82062306a36Sopenharmony_ci * @mcq_capabilities: UFS Multi Circular Queue capabilities
82162306a36Sopenharmony_ci * @nutrs: Transfer Request Queue depth supported by controller
82262306a36Sopenharmony_ci * @nutmrs: Task Management Queue depth supported by controller
82362306a36Sopenharmony_ci * @reserved_slot: Used to submit device commands. Protected by @dev_cmd.lock.
82462306a36Sopenharmony_ci * @ufs_version: UFS Version to which controller complies
82562306a36Sopenharmony_ci * @vops: pointer to variant specific operations
82662306a36Sopenharmony_ci * @vps: pointer to variant specific parameters
82762306a36Sopenharmony_ci * @priv: pointer to variant specific private data
82862306a36Sopenharmony_ci * @sg_entry_size: size of struct ufshcd_sg_entry (may include variant fields)
82962306a36Sopenharmony_ci * @irq: Irq number of the controller
83062306a36Sopenharmony_ci * @is_irq_enabled: whether or not the UFS controller interrupt is enabled.
83162306a36Sopenharmony_ci * @dev_ref_clk_freq: reference clock frequency
83262306a36Sopenharmony_ci * @quirks: bitmask with information about deviations from the UFSHCI standard.
83362306a36Sopenharmony_ci * @dev_quirks: bitmask with information about deviations from the UFS standard.
83462306a36Sopenharmony_ci * @tmf_tag_set: TMF tag set.
83562306a36Sopenharmony_ci * @tmf_queue: Used to allocate TMF tags.
83662306a36Sopenharmony_ci * @tmf_rqs: array with pointers to TMF requests while these are in progress.
83762306a36Sopenharmony_ci * @active_uic_cmd: handle of active UIC command
83862306a36Sopenharmony_ci * @uic_cmd_mutex: mutex for UIC command
83962306a36Sopenharmony_ci * @uic_async_done: completion used during UIC processing
84062306a36Sopenharmony_ci * @ufshcd_state: UFSHCD state
84162306a36Sopenharmony_ci * @eh_flags: Error handling flags
84262306a36Sopenharmony_ci * @intr_mask: Interrupt Mask Bits
84362306a36Sopenharmony_ci * @ee_ctrl_mask: Exception event control mask
84462306a36Sopenharmony_ci * @ee_drv_mask: Exception event mask for driver
84562306a36Sopenharmony_ci * @ee_usr_mask: Exception event mask for user (set via debugfs)
84662306a36Sopenharmony_ci * @ee_ctrl_mutex: Used to serialize exception event information.
84762306a36Sopenharmony_ci * @is_powered: flag to check if HBA is powered
84862306a36Sopenharmony_ci * @shutting_down: flag to check if shutdown has been invoked
84962306a36Sopenharmony_ci * @host_sem: semaphore used to serialize concurrent contexts
85062306a36Sopenharmony_ci * @eh_wq: Workqueue that eh_work works on
85162306a36Sopenharmony_ci * @eh_work: Worker to handle UFS errors that require s/w attention
85262306a36Sopenharmony_ci * @eeh_work: Worker to handle exception events
85362306a36Sopenharmony_ci * @errors: HBA errors
85462306a36Sopenharmony_ci * @uic_error: UFS interconnect layer error status
85562306a36Sopenharmony_ci * @saved_err: sticky error mask
85662306a36Sopenharmony_ci * @saved_uic_err: sticky UIC error mask
85762306a36Sopenharmony_ci * @ufs_stats: various error counters
85862306a36Sopenharmony_ci * @force_reset: flag to force eh_work perform a full reset
85962306a36Sopenharmony_ci * @force_pmc: flag to force a power mode change
86062306a36Sopenharmony_ci * @silence_err_logs: flag to silence error logs
86162306a36Sopenharmony_ci * @dev_cmd: ufs device management command information
86262306a36Sopenharmony_ci * @last_dme_cmd_tstamp: time stamp of the last completed DME command
86362306a36Sopenharmony_ci * @nop_out_timeout: NOP OUT timeout value
86462306a36Sopenharmony_ci * @dev_info: information about the UFS device
86562306a36Sopenharmony_ci * @auto_bkops_enabled: to track whether bkops is enabled in device
86662306a36Sopenharmony_ci * @vreg_info: UFS device voltage regulator information
86762306a36Sopenharmony_ci * @clk_list_head: UFS host controller clocks list node head
86862306a36Sopenharmony_ci * @req_abort_count: number of times ufshcd_abort() has been called
86962306a36Sopenharmony_ci * @lanes_per_direction: number of lanes per data direction between the UFS
87062306a36Sopenharmony_ci *	controller and the UFS device.
87162306a36Sopenharmony_ci * @pwr_info: holds current power mode
87262306a36Sopenharmony_ci * @max_pwr_info: keeps the device max valid pwm
87362306a36Sopenharmony_ci * @clk_gating: information related to clock gating
87462306a36Sopenharmony_ci * @caps: bitmask with information about UFS controller capabilities
87562306a36Sopenharmony_ci * @devfreq: frequency scaling information owned by the devfreq core
87662306a36Sopenharmony_ci * @clk_scaling: frequency scaling information owned by the UFS driver
87762306a36Sopenharmony_ci * @system_suspending: system suspend has been started and system resume has
87862306a36Sopenharmony_ci *	not yet finished.
87962306a36Sopenharmony_ci * @is_sys_suspended: UFS device has been suspended because of system suspend
88062306a36Sopenharmony_ci * @urgent_bkops_lvl: keeps track of urgent bkops level for device
88162306a36Sopenharmony_ci * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
88262306a36Sopenharmony_ci *  device is known or not.
88362306a36Sopenharmony_ci * @wb_mutex: used to serialize devfreq and sysfs write booster toggling
88462306a36Sopenharmony_ci * @clk_scaling_lock: used to serialize device commands and clock scaling
88562306a36Sopenharmony_ci * @desc_size: descriptor sizes reported by device
88662306a36Sopenharmony_ci * @scsi_block_reqs_cnt: reference counting for scsi block requests
88762306a36Sopenharmony_ci * @bsg_dev: struct device associated with the BSG queue
88862306a36Sopenharmony_ci * @bsg_queue: BSG queue associated with the UFS controller
88962306a36Sopenharmony_ci * @rpm_dev_flush_recheck_work: used to suspend from RPM (runtime power
89062306a36Sopenharmony_ci *	management) after the UFS device has finished a WriteBooster buffer
89162306a36Sopenharmony_ci *	flush or auto BKOP.
89262306a36Sopenharmony_ci * @monitor: statistics about UFS commands
89362306a36Sopenharmony_ci * @crypto_capabilities: Content of crypto capabilities register (0x100)
89462306a36Sopenharmony_ci * @crypto_cap_array: Array of crypto capabilities
89562306a36Sopenharmony_ci * @crypto_cfg_register: Start of the crypto cfg array
89662306a36Sopenharmony_ci * @crypto_profile: the crypto profile of this hba (if applicable)
89762306a36Sopenharmony_ci * @debugfs_root: UFS controller debugfs root directory
89862306a36Sopenharmony_ci * @debugfs_ee_work: used to restore ee_ctrl_mask after a delay
89962306a36Sopenharmony_ci * @debugfs_ee_rate_limit_ms: user configurable delay after which to restore
90062306a36Sopenharmony_ci *	ee_ctrl_mask
90162306a36Sopenharmony_ci * @luns_avail: number of regular and well known LUNs supported by the UFS
90262306a36Sopenharmony_ci *	device
90362306a36Sopenharmony_ci * @nr_hw_queues: number of hardware queues configured
90462306a36Sopenharmony_ci * @nr_queues: number of Queues of different queue types
90562306a36Sopenharmony_ci * @complete_put: whether or not to call ufshcd_rpm_put() from inside
90662306a36Sopenharmony_ci *	ufshcd_resume_complete()
90762306a36Sopenharmony_ci * @ext_iid_sup: is EXT_IID is supported by UFSHC
90862306a36Sopenharmony_ci * @mcq_sup: is mcq supported by UFSHC
90962306a36Sopenharmony_ci * @mcq_enabled: is mcq ready to accept requests
91062306a36Sopenharmony_ci * @res: array of resource info of MCQ registers
91162306a36Sopenharmony_ci * @mcq_base: Multi circular queue registers base address
91262306a36Sopenharmony_ci * @uhq: array of supported hardware queues
91362306a36Sopenharmony_ci * @dev_cmd_queue: Queue for issuing device management commands
91462306a36Sopenharmony_ci */
91562306a36Sopenharmony_cistruct ufs_hba {
91662306a36Sopenharmony_ci	void __iomem *mmio_base;
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	/* Virtual memory reference */
91962306a36Sopenharmony_ci	struct utp_transfer_cmd_desc *ucdl_base_addr;
92062306a36Sopenharmony_ci	struct utp_transfer_req_desc *utrdl_base_addr;
92162306a36Sopenharmony_ci	struct utp_task_req_desc *utmrdl_base_addr;
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	/* DMA memory reference */
92462306a36Sopenharmony_ci	dma_addr_t ucdl_dma_addr;
92562306a36Sopenharmony_ci	dma_addr_t utrdl_dma_addr;
92662306a36Sopenharmony_ci	dma_addr_t utmrdl_dma_addr;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	struct Scsi_Host *host;
92962306a36Sopenharmony_ci	struct device *dev;
93062306a36Sopenharmony_ci	struct scsi_device *ufs_device_wlun;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci#ifdef CONFIG_SCSI_UFS_HWMON
93362306a36Sopenharmony_ci	struct device *hwmon_device;
93462306a36Sopenharmony_ci#endif
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	enum ufs_dev_pwr_mode curr_dev_pwr_mode;
93762306a36Sopenharmony_ci	enum uic_link_state uic_link_state;
93862306a36Sopenharmony_ci	/* Desired UFS power management level during runtime PM */
93962306a36Sopenharmony_ci	enum ufs_pm_level rpm_lvl;
94062306a36Sopenharmony_ci	/* Desired UFS power management level during system PM */
94162306a36Sopenharmony_ci	enum ufs_pm_level spm_lvl;
94262306a36Sopenharmony_ci	int pm_op_in_progress;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	/* Auto-Hibernate Idle Timer register value */
94562306a36Sopenharmony_ci	u32 ahit;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	struct ufshcd_lrb *lrb;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	unsigned long outstanding_tasks;
95062306a36Sopenharmony_ci	spinlock_t outstanding_lock;
95162306a36Sopenharmony_ci	unsigned long outstanding_reqs;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	u32 capabilities;
95462306a36Sopenharmony_ci	int nutrs;
95562306a36Sopenharmony_ci	u32 mcq_capabilities;
95662306a36Sopenharmony_ci	int nutmrs;
95762306a36Sopenharmony_ci	u32 reserved_slot;
95862306a36Sopenharmony_ci	u32 ufs_version;
95962306a36Sopenharmony_ci	const struct ufs_hba_variant_ops *vops;
96062306a36Sopenharmony_ci	struct ufs_hba_variant_params *vps;
96162306a36Sopenharmony_ci	void *priv;
96262306a36Sopenharmony_ci#ifdef CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE
96362306a36Sopenharmony_ci	size_t sg_entry_size;
96462306a36Sopenharmony_ci#endif
96562306a36Sopenharmony_ci	unsigned int irq;
96662306a36Sopenharmony_ci	bool is_irq_enabled;
96762306a36Sopenharmony_ci	enum ufs_ref_clk_freq dev_ref_clk_freq;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	unsigned int quirks;	/* Deviations from standard UFSHCI spec. */
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	/* Device deviations from standard UFS device spec. */
97262306a36Sopenharmony_ci	unsigned int dev_quirks;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	struct blk_mq_tag_set tmf_tag_set;
97562306a36Sopenharmony_ci	struct request_queue *tmf_queue;
97662306a36Sopenharmony_ci	struct request **tmf_rqs;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	struct uic_command *active_uic_cmd;
97962306a36Sopenharmony_ci	struct mutex uic_cmd_mutex;
98062306a36Sopenharmony_ci	struct completion *uic_async_done;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	enum ufshcd_state ufshcd_state;
98362306a36Sopenharmony_ci	u32 eh_flags;
98462306a36Sopenharmony_ci	u32 intr_mask;
98562306a36Sopenharmony_ci	u16 ee_ctrl_mask;
98662306a36Sopenharmony_ci	u16 ee_drv_mask;
98762306a36Sopenharmony_ci	u16 ee_usr_mask;
98862306a36Sopenharmony_ci	struct mutex ee_ctrl_mutex;
98962306a36Sopenharmony_ci	bool is_powered;
99062306a36Sopenharmony_ci	bool shutting_down;
99162306a36Sopenharmony_ci	struct semaphore host_sem;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	/* Work Queues */
99462306a36Sopenharmony_ci	struct workqueue_struct *eh_wq;
99562306a36Sopenharmony_ci	struct work_struct eh_work;
99662306a36Sopenharmony_ci	struct work_struct eeh_work;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	/* HBA Errors */
99962306a36Sopenharmony_ci	u32 errors;
100062306a36Sopenharmony_ci	u32 uic_error;
100162306a36Sopenharmony_ci	u32 saved_err;
100262306a36Sopenharmony_ci	u32 saved_uic_err;
100362306a36Sopenharmony_ci	struct ufs_stats ufs_stats;
100462306a36Sopenharmony_ci	bool force_reset;
100562306a36Sopenharmony_ci	bool force_pmc;
100662306a36Sopenharmony_ci	bool silence_err_logs;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	/* Device management request data */
100962306a36Sopenharmony_ci	struct ufs_dev_cmd dev_cmd;
101062306a36Sopenharmony_ci	ktime_t last_dme_cmd_tstamp;
101162306a36Sopenharmony_ci	int nop_out_timeout;
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	/* Keeps information of the UFS device connected to this host */
101462306a36Sopenharmony_ci	struct ufs_dev_info dev_info;
101562306a36Sopenharmony_ci	bool auto_bkops_enabled;
101662306a36Sopenharmony_ci	struct ufs_vreg_info vreg_info;
101762306a36Sopenharmony_ci	struct list_head clk_list_head;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	/* Number of requests aborts */
102062306a36Sopenharmony_ci	int req_abort_count;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	/* Number of lanes available (1 or 2) for Rx/Tx */
102362306a36Sopenharmony_ci	u32 lanes_per_direction;
102462306a36Sopenharmony_ci	struct ufs_pa_layer_attr pwr_info;
102562306a36Sopenharmony_ci	struct ufs_pwr_mode_info max_pwr_info;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	struct ufs_clk_gating clk_gating;
102862306a36Sopenharmony_ci	/* Control to enable/disable host capabilities */
102962306a36Sopenharmony_ci	u32 caps;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	struct devfreq *devfreq;
103262306a36Sopenharmony_ci	struct ufs_clk_scaling clk_scaling;
103362306a36Sopenharmony_ci	bool system_suspending;
103462306a36Sopenharmony_ci	bool is_sys_suspended;
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	enum bkops_status urgent_bkops_lvl;
103762306a36Sopenharmony_ci	bool is_urgent_bkops_lvl_checked;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	struct mutex wb_mutex;
104062306a36Sopenharmony_ci	struct rw_semaphore clk_scaling_lock;
104162306a36Sopenharmony_ci	atomic_t scsi_block_reqs_cnt;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	struct device		bsg_dev;
104462306a36Sopenharmony_ci	struct request_queue	*bsg_queue;
104562306a36Sopenharmony_ci	struct delayed_work rpm_dev_flush_recheck_work;
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	struct ufs_hba_monitor	monitor;
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci#ifdef CONFIG_SCSI_UFS_CRYPTO
105062306a36Sopenharmony_ci	union ufs_crypto_capabilities crypto_capabilities;
105162306a36Sopenharmony_ci	union ufs_crypto_cap_entry *crypto_cap_array;
105262306a36Sopenharmony_ci	u32 crypto_cfg_register;
105362306a36Sopenharmony_ci	struct blk_crypto_profile crypto_profile;
105462306a36Sopenharmony_ci#endif
105562306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
105662306a36Sopenharmony_ci	struct dentry *debugfs_root;
105762306a36Sopenharmony_ci	struct delayed_work debugfs_ee_work;
105862306a36Sopenharmony_ci	u32 debugfs_ee_rate_limit_ms;
105962306a36Sopenharmony_ci#endif
106062306a36Sopenharmony_ci	u32 luns_avail;
106162306a36Sopenharmony_ci	unsigned int nr_hw_queues;
106262306a36Sopenharmony_ci	unsigned int nr_queues[HCTX_MAX_TYPES];
106362306a36Sopenharmony_ci	bool complete_put;
106462306a36Sopenharmony_ci	bool ext_iid_sup;
106562306a36Sopenharmony_ci	bool scsi_host_added;
106662306a36Sopenharmony_ci	bool mcq_sup;
106762306a36Sopenharmony_ci	bool mcq_enabled;
106862306a36Sopenharmony_ci	struct ufshcd_res_info res[RES_MAX];
106962306a36Sopenharmony_ci	void __iomem *mcq_base;
107062306a36Sopenharmony_ci	struct ufs_hw_queue *uhq;
107162306a36Sopenharmony_ci	struct ufs_hw_queue *dev_cmd_queue;
107262306a36Sopenharmony_ci	struct ufshcd_mcq_opr_info_t mcq_opr[OPR_MAX];
107362306a36Sopenharmony_ci};
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci/**
107662306a36Sopenharmony_ci * struct ufs_hw_queue - per hardware queue structure
107762306a36Sopenharmony_ci * @mcq_sq_head: base address of submission queue head pointer
107862306a36Sopenharmony_ci * @mcq_sq_tail: base address of submission queue tail pointer
107962306a36Sopenharmony_ci * @mcq_cq_head: base address of completion queue head pointer
108062306a36Sopenharmony_ci * @mcq_cq_tail: base address of completion queue tail pointer
108162306a36Sopenharmony_ci * @sqe_base_addr: submission queue entry base address
108262306a36Sopenharmony_ci * @sqe_dma_addr: submission queue dma address
108362306a36Sopenharmony_ci * @cqe_base_addr: completion queue base address
108462306a36Sopenharmony_ci * @cqe_dma_addr: completion queue dma address
108562306a36Sopenharmony_ci * @max_entries: max number of slots in this hardware queue
108662306a36Sopenharmony_ci * @id: hardware queue ID
108762306a36Sopenharmony_ci * @sq_tp_slot: current slot to which SQ tail pointer is pointing
108862306a36Sopenharmony_ci * @sq_lock: serialize submission queue access
108962306a36Sopenharmony_ci * @cq_tail_slot: current slot to which CQ tail pointer is pointing
109062306a36Sopenharmony_ci * @cq_head_slot: current slot to which CQ head pointer is pointing
109162306a36Sopenharmony_ci * @cq_lock: Synchronize between multiple polling instances
109262306a36Sopenharmony_ci * @sq_mutex: prevent submission queue concurrent access
109362306a36Sopenharmony_ci */
109462306a36Sopenharmony_cistruct ufs_hw_queue {
109562306a36Sopenharmony_ci	void __iomem *mcq_sq_head;
109662306a36Sopenharmony_ci	void __iomem *mcq_sq_tail;
109762306a36Sopenharmony_ci	void __iomem *mcq_cq_head;
109862306a36Sopenharmony_ci	void __iomem *mcq_cq_tail;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	struct utp_transfer_req_desc *sqe_base_addr;
110162306a36Sopenharmony_ci	dma_addr_t sqe_dma_addr;
110262306a36Sopenharmony_ci	struct cq_entry *cqe_base_addr;
110362306a36Sopenharmony_ci	dma_addr_t cqe_dma_addr;
110462306a36Sopenharmony_ci	u32 max_entries;
110562306a36Sopenharmony_ci	u32 id;
110662306a36Sopenharmony_ci	u32 sq_tail_slot;
110762306a36Sopenharmony_ci	spinlock_t sq_lock;
110862306a36Sopenharmony_ci	u32 cq_tail_slot;
110962306a36Sopenharmony_ci	u32 cq_head_slot;
111062306a36Sopenharmony_ci	spinlock_t cq_lock;
111162306a36Sopenharmony_ci	/* prevent concurrent access to submission queue */
111262306a36Sopenharmony_ci	struct mutex sq_mutex;
111362306a36Sopenharmony_ci};
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cistatic inline bool is_mcq_enabled(struct ufs_hba *hba)
111662306a36Sopenharmony_ci{
111762306a36Sopenharmony_ci	return hba->mcq_enabled;
111862306a36Sopenharmony_ci}
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci#ifdef CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE
112162306a36Sopenharmony_cistatic inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
112262306a36Sopenharmony_ci{
112362306a36Sopenharmony_ci	return hba->sg_entry_size;
112462306a36Sopenharmony_ci}
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_cistatic inline void ufshcd_set_sg_entry_size(struct ufs_hba *hba, size_t sg_entry_size)
112762306a36Sopenharmony_ci{
112862306a36Sopenharmony_ci	WARN_ON_ONCE(sg_entry_size < sizeof(struct ufshcd_sg_entry));
112962306a36Sopenharmony_ci	hba->sg_entry_size = sg_entry_size;
113062306a36Sopenharmony_ci}
113162306a36Sopenharmony_ci#else
113262306a36Sopenharmony_cistatic inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
113362306a36Sopenharmony_ci{
113462306a36Sopenharmony_ci	return sizeof(struct ufshcd_sg_entry);
113562306a36Sopenharmony_ci}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci#define ufshcd_set_sg_entry_size(hba, sg_entry_size)                   \
113862306a36Sopenharmony_ci	({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); })
113962306a36Sopenharmony_ci#endif
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_cistatic inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba)
114262306a36Sopenharmony_ci{
114362306a36Sopenharmony_ci	return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba);
114462306a36Sopenharmony_ci}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci/* Returns true if clocks can be gated. Otherwise false */
114762306a36Sopenharmony_cistatic inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba)
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	return hba->caps & UFSHCD_CAP_CLK_GATING;
115062306a36Sopenharmony_ci}
115162306a36Sopenharmony_cistatic inline bool ufshcd_can_hibern8_during_gating(struct ufs_hba *hba)
115262306a36Sopenharmony_ci{
115362306a36Sopenharmony_ci	return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
115462306a36Sopenharmony_ci}
115562306a36Sopenharmony_cistatic inline int ufshcd_is_clkscaling_supported(struct ufs_hba *hba)
115662306a36Sopenharmony_ci{
115762306a36Sopenharmony_ci	return hba->caps & UFSHCD_CAP_CLK_SCALING;
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_cistatic inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba)
116062306a36Sopenharmony_ci{
116162306a36Sopenharmony_ci	return hba->caps & UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
116262306a36Sopenharmony_ci}
116362306a36Sopenharmony_cistatic inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba)
116462306a36Sopenharmony_ci{
116562306a36Sopenharmony_ci	return hba->caps & UFSHCD_CAP_RPM_AUTOSUSPEND;
116662306a36Sopenharmony_ci}
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_cistatic inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba)
116962306a36Sopenharmony_ci{
117062306a36Sopenharmony_ci	return (hba->caps & UFSHCD_CAP_INTR_AGGR) &&
117162306a36Sopenharmony_ci		!(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR);
117262306a36Sopenharmony_ci}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_cistatic inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba)
117562306a36Sopenharmony_ci{
117662306a36Sopenharmony_ci	return !!(ufshcd_is_link_hibern8(hba) &&
117762306a36Sopenharmony_ci		  (hba->caps & UFSHCD_CAP_AGGR_POWER_COLLAPSE));
117862306a36Sopenharmony_ci}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_cistatic inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba)
118162306a36Sopenharmony_ci{
118262306a36Sopenharmony_ci	return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) &&
118362306a36Sopenharmony_ci		!(hba->quirks & UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8);
118462306a36Sopenharmony_ci}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_cistatic inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba)
118762306a36Sopenharmony_ci{
118862306a36Sopenharmony_ci	return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit);
118962306a36Sopenharmony_ci}
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_cistatic inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba)
119262306a36Sopenharmony_ci{
119362306a36Sopenharmony_ci	return hba->caps & UFSHCD_CAP_WB_EN;
119462306a36Sopenharmony_ci}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_cistatic inline bool ufshcd_enable_wb_if_scaling_up(struct ufs_hba *hba)
119762306a36Sopenharmony_ci{
119862306a36Sopenharmony_ci	return hba->caps & UFSHCD_CAP_WB_WITH_CLK_SCALING;
119962306a36Sopenharmony_ci}
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci#define ufsmcq_writel(hba, val, reg)	\
120262306a36Sopenharmony_ci	writel((val), (hba)->mcq_base + (reg))
120362306a36Sopenharmony_ci#define ufsmcq_readl(hba, reg)	\
120462306a36Sopenharmony_ci	readl((hba)->mcq_base + (reg))
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci#define ufsmcq_writelx(hba, val, reg)	\
120762306a36Sopenharmony_ci	writel_relaxed((val), (hba)->mcq_base + (reg))
120862306a36Sopenharmony_ci#define ufsmcq_readlx(hba, reg)	\
120962306a36Sopenharmony_ci	readl_relaxed((hba)->mcq_base + (reg))
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci#define ufshcd_writel(hba, val, reg)	\
121262306a36Sopenharmony_ci	writel((val), (hba)->mmio_base + (reg))
121362306a36Sopenharmony_ci#define ufshcd_readl(hba, reg)	\
121462306a36Sopenharmony_ci	readl((hba)->mmio_base + (reg))
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci/**
121762306a36Sopenharmony_ci * ufshcd_rmwl - perform read/modify/write for a controller register
121862306a36Sopenharmony_ci * @hba: per adapter instance
121962306a36Sopenharmony_ci * @mask: mask to apply on read value
122062306a36Sopenharmony_ci * @val: actual value to write
122162306a36Sopenharmony_ci * @reg: register address
122262306a36Sopenharmony_ci */
122362306a36Sopenharmony_cistatic inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
122462306a36Sopenharmony_ci{
122562306a36Sopenharmony_ci	u32 tmp;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	tmp = ufshcd_readl(hba, reg);
122862306a36Sopenharmony_ci	tmp &= ~mask;
122962306a36Sopenharmony_ci	tmp |= (val & mask);
123062306a36Sopenharmony_ci	ufshcd_writel(hba, tmp, reg);
123162306a36Sopenharmony_ci}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ciint ufshcd_alloc_host(struct device *, struct ufs_hba **);
123462306a36Sopenharmony_civoid ufshcd_dealloc_host(struct ufs_hba *);
123562306a36Sopenharmony_ciint ufshcd_hba_enable(struct ufs_hba *hba);
123662306a36Sopenharmony_ciint ufshcd_init(struct ufs_hba *, void __iomem *, unsigned int);
123762306a36Sopenharmony_ciint ufshcd_link_recovery(struct ufs_hba *hba);
123862306a36Sopenharmony_ciint ufshcd_make_hba_operational(struct ufs_hba *hba);
123962306a36Sopenharmony_civoid ufshcd_remove(struct ufs_hba *);
124062306a36Sopenharmony_ciint ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
124162306a36Sopenharmony_ciint ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
124262306a36Sopenharmony_civoid ufshcd_delay_us(unsigned long us, unsigned long tolerance);
124362306a36Sopenharmony_civoid ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk);
124462306a36Sopenharmony_civoid ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val);
124562306a36Sopenharmony_civoid ufshcd_hba_stop(struct ufs_hba *hba);
124662306a36Sopenharmony_civoid ufshcd_schedule_eh_work(struct ufs_hba *hba);
124762306a36Sopenharmony_civoid ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds);
124862306a36Sopenharmony_ciu32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i);
124962306a36Sopenharmony_civoid ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i);
125062306a36Sopenharmony_ciunsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
125162306a36Sopenharmony_ci					 struct ufs_hw_queue *hwq);
125262306a36Sopenharmony_civoid ufshcd_mcq_make_queues_operational(struct ufs_hba *hba);
125362306a36Sopenharmony_civoid ufshcd_mcq_enable_esi(struct ufs_hba *hba);
125462306a36Sopenharmony_civoid ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg);
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci/**
125762306a36Sopenharmony_ci * ufshcd_set_variant - set variant specific data to the hba
125862306a36Sopenharmony_ci * @hba: per adapter instance
125962306a36Sopenharmony_ci * @variant: pointer to variant specific data
126062306a36Sopenharmony_ci */
126162306a36Sopenharmony_cistatic inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant)
126262306a36Sopenharmony_ci{
126362306a36Sopenharmony_ci	BUG_ON(!hba);
126462306a36Sopenharmony_ci	hba->priv = variant;
126562306a36Sopenharmony_ci}
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci/**
126862306a36Sopenharmony_ci * ufshcd_get_variant - get variant specific data from the hba
126962306a36Sopenharmony_ci * @hba: per adapter instance
127062306a36Sopenharmony_ci */
127162306a36Sopenharmony_cistatic inline void *ufshcd_get_variant(struct ufs_hba *hba)
127262306a36Sopenharmony_ci{
127362306a36Sopenharmony_ci	BUG_ON(!hba);
127462306a36Sopenharmony_ci	return hba->priv;
127562306a36Sopenharmony_ci}
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci#ifdef CONFIG_PM
127862306a36Sopenharmony_ciextern int ufshcd_runtime_suspend(struct device *dev);
127962306a36Sopenharmony_ciextern int ufshcd_runtime_resume(struct device *dev);
128062306a36Sopenharmony_ci#endif
128162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
128262306a36Sopenharmony_ciextern int ufshcd_system_suspend(struct device *dev);
128362306a36Sopenharmony_ciextern int ufshcd_system_resume(struct device *dev);
128462306a36Sopenharmony_ciextern int ufshcd_system_freeze(struct device *dev);
128562306a36Sopenharmony_ciextern int ufshcd_system_thaw(struct device *dev);
128662306a36Sopenharmony_ciextern int ufshcd_system_restore(struct device *dev);
128762306a36Sopenharmony_ci#endif
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ciextern int ufshcd_dme_configure_adapt(struct ufs_hba *hba,
129062306a36Sopenharmony_ci				      int agreed_gear,
129162306a36Sopenharmony_ci				      int adapt_val);
129262306a36Sopenharmony_ciextern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
129362306a36Sopenharmony_ci			       u8 attr_set, u32 mib_val, u8 peer);
129462306a36Sopenharmony_ciextern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
129562306a36Sopenharmony_ci			       u32 *mib_val, u8 peer);
129662306a36Sopenharmony_ciextern int ufshcd_config_pwr_mode(struct ufs_hba *hba,
129762306a36Sopenharmony_ci			struct ufs_pa_layer_attr *desired_pwr_mode);
129862306a36Sopenharmony_ciextern int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode);
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci/* UIC command interfaces for DME primitives */
130162306a36Sopenharmony_ci#define DME_LOCAL	0
130262306a36Sopenharmony_ci#define DME_PEER	1
130362306a36Sopenharmony_ci#define ATTR_SET_NOR	0	/* NORMAL */
130462306a36Sopenharmony_ci#define ATTR_SET_ST	1	/* STATIC */
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_cistatic inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
130762306a36Sopenharmony_ci				 u32 mib_val)
130862306a36Sopenharmony_ci{
130962306a36Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
131062306a36Sopenharmony_ci				   mib_val, DME_LOCAL);
131162306a36Sopenharmony_ci}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_cistatic inline int ufshcd_dme_st_set(struct ufs_hba *hba, u32 attr_sel,
131462306a36Sopenharmony_ci				    u32 mib_val)
131562306a36Sopenharmony_ci{
131662306a36Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
131762306a36Sopenharmony_ci				   mib_val, DME_LOCAL);
131862306a36Sopenharmony_ci}
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_cistatic inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
132162306a36Sopenharmony_ci				      u32 mib_val)
132262306a36Sopenharmony_ci{
132362306a36Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
132462306a36Sopenharmony_ci				   mib_val, DME_PEER);
132562306a36Sopenharmony_ci}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_cistatic inline int ufshcd_dme_peer_st_set(struct ufs_hba *hba, u32 attr_sel,
132862306a36Sopenharmony_ci					 u32 mib_val)
132962306a36Sopenharmony_ci{
133062306a36Sopenharmony_ci	return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
133162306a36Sopenharmony_ci				   mib_val, DME_PEER);
133262306a36Sopenharmony_ci}
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_cistatic inline int ufshcd_dme_get(struct ufs_hba *hba,
133562306a36Sopenharmony_ci				 u32 attr_sel, u32 *mib_val)
133662306a36Sopenharmony_ci{
133762306a36Sopenharmony_ci	return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL);
133862306a36Sopenharmony_ci}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_cistatic inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
134162306a36Sopenharmony_ci				      u32 attr_sel, u32 *mib_val)
134262306a36Sopenharmony_ci{
134362306a36Sopenharmony_ci	return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
134462306a36Sopenharmony_ci}
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_cistatic inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
134762306a36Sopenharmony_ci{
134862306a36Sopenharmony_ci	return (pwr_info->pwr_rx == FAST_MODE ||
134962306a36Sopenharmony_ci		pwr_info->pwr_rx == FASTAUTO_MODE) &&
135062306a36Sopenharmony_ci		(pwr_info->pwr_tx == FAST_MODE ||
135162306a36Sopenharmony_ci		pwr_info->pwr_tx == FASTAUTO_MODE);
135262306a36Sopenharmony_ci}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_cistatic inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba)
135562306a36Sopenharmony_ci{
135662306a36Sopenharmony_ci	return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
135762306a36Sopenharmony_ci}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_civoid ufshcd_auto_hibern8_enable(struct ufs_hba *hba);
136062306a36Sopenharmony_civoid ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
136162306a36Sopenharmony_civoid ufshcd_fixup_dev_quirks(struct ufs_hba *hba,
136262306a36Sopenharmony_ci			     const struct ufs_dev_quirk *fixups);
136362306a36Sopenharmony_ci#define SD_ASCII_STD true
136462306a36Sopenharmony_ci#define SD_RAW false
136562306a36Sopenharmony_ciint ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
136662306a36Sopenharmony_ci			    u8 **buf, bool ascii);
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_civoid ufshcd_hold(struct ufs_hba *hba);
136962306a36Sopenharmony_civoid ufshcd_release(struct ufs_hba *hba);
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_civoid ufshcd_clkgate_delay_set(struct device *dev, unsigned long value);
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ciu32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ciint ufshcd_get_vreg(struct device *dev, struct ufs_vreg *vreg);
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ciint ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ciint ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu,
138062306a36Sopenharmony_ci				     struct utp_upiu_req *rsp_upiu, struct ufs_ehs *ehs_req,
138162306a36Sopenharmony_ci				     struct ufs_ehs *ehs_rsp, int sg_cnt,
138262306a36Sopenharmony_ci				     struct scatterlist *sg_list, enum dma_data_direction dir);
138362306a36Sopenharmony_ciint ufshcd_wb_toggle(struct ufs_hba *hba, bool enable);
138462306a36Sopenharmony_ciint ufshcd_wb_toggle_buf_flush(struct ufs_hba *hba, bool enable);
138562306a36Sopenharmony_ciint ufshcd_suspend_prepare(struct device *dev);
138662306a36Sopenharmony_ciint __ufshcd_suspend_prepare(struct device *dev, bool rpm_ok_for_spm);
138762306a36Sopenharmony_civoid ufshcd_resume_complete(struct device *dev);
138862306a36Sopenharmony_cibool ufshcd_is_hba_active(struct ufs_hba *hba);
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci/* Wrapper functions for safely calling variant operations */
139162306a36Sopenharmony_cistatic inline int ufshcd_vops_init(struct ufs_hba *hba)
139262306a36Sopenharmony_ci{
139362306a36Sopenharmony_ci	if (hba->vops && hba->vops->init)
139462306a36Sopenharmony_ci		return hba->vops->init(hba);
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	return 0;
139762306a36Sopenharmony_ci}
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_cistatic inline int ufshcd_vops_phy_initialization(struct ufs_hba *hba)
140062306a36Sopenharmony_ci{
140162306a36Sopenharmony_ci	if (hba->vops && hba->vops->phy_initialization)
140262306a36Sopenharmony_ci		return hba->vops->phy_initialization(hba);
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	return 0;
140562306a36Sopenharmony_ci}
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ciextern const struct ufs_pm_lvl_states ufs_pm_lvl_states[];
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ciint ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
141062306a36Sopenharmony_ci		     const char *prefix);
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ciint __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask);
141362306a36Sopenharmony_ciint ufshcd_write_ee_control(struct ufs_hba *hba);
141462306a36Sopenharmony_ciint ufshcd_update_ee_control(struct ufs_hba *hba, u16 *mask,
141562306a36Sopenharmony_ci			     const u16 *other_mask, u16 set, u16 clr);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci#endif /* End of Header */
1418