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