167351119SBean Huo /* SPDX-License-Identifier: GPL-2.0-or-later */ 2e0eca63eSVinayak Holikatti /* 3e0eca63eSVinayak Holikatti * Universal Flash Storage Host controller driver 4e0eca63eSVinayak Holikatti * Copyright (C) 2011-2013 Samsung India Software Operations 5dc3c8d3aSYaniv Gardi * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. 6e0eca63eSVinayak Holikatti * 7e0eca63eSVinayak Holikatti * Authors: 8e0eca63eSVinayak Holikatti * Santosh Yaraganavi <santosh.sy@samsung.com> 9e0eca63eSVinayak Holikatti * Vinayak Holikatti <h.vinayak@samsung.com> 10e0eca63eSVinayak Holikatti */ 11e0eca63eSVinayak Holikatti 12e0eca63eSVinayak Holikatti #ifndef _UFSHCD_H 13e0eca63eSVinayak Holikatti #define _UFSHCD_H 14e0eca63eSVinayak Holikatti 155a244e0eSStanley Chu #include <linux/bitfield.h> 161e8d44bdSEric Biggers #include <linux/blk-crypto-profile.h> 173f06f780SBart Van Assche #include <linux/blk-mq.h> 183f06f780SBart Van Assche #include <linux/devfreq.h> 19045da307SAkinobu Mita #include <linux/fault-inject.h> 206ce2082fSJani Nikula #include <linux/debugfs.h> 21e02288e0SCan Guo #include <linux/msi.h> 223f06f780SBart Van Assche #include <linux/pm_runtime.h> 23f3e57da5SBean Huo #include <linux/dma-direction.h> 243f06f780SBart Van Assche #include <scsi/scsi_device.h> 25cce9fd60SBart Van Assche #include <scsi/scsi_host.h> 26dd11376bSBart Van Assche #include <ufs/unipro.h> 27dd11376bSBart Van Assche #include <ufs/ufs.h> 28dd11376bSBart Van Assche #include <ufs/ufs_quirks.h> 29dd11376bSBart Van Assche #include <ufs/ufshci.h> 30e0eca63eSVinayak Holikatti 31e0eca63eSVinayak Holikatti #define UFSHCD "ufshcd" 32e0eca63eSVinayak Holikatti 33858231bdSBart Van Assche struct scsi_device; 345c0c28a8SSujit Reddy Thumma struct ufs_hba; 355c0c28a8SSujit Reddy Thumma 365a0b0cb9SSujit Reddy Thumma enum dev_cmd_type { 375a0b0cb9SSujit Reddy Thumma DEV_CMD_TYPE_NOP = 0x0, 3868078d5cSDolev Raviv DEV_CMD_TYPE_QUERY = 0x1, 396ff265fcSBean Huo DEV_CMD_TYPE_RPMB = 0x2, 405a0b0cb9SSujit Reddy Thumma }; 415a0b0cb9SSujit Reddy Thumma 42e965e5e0SStanley Chu enum ufs_event_type { 43e965e5e0SStanley Chu /* uic specific errors */ 44e965e5e0SStanley Chu UFS_EVT_PA_ERR = 0, 45e965e5e0SStanley Chu UFS_EVT_DL_ERR, 46e965e5e0SStanley Chu UFS_EVT_NL_ERR, 47e965e5e0SStanley Chu UFS_EVT_TL_ERR, 48e965e5e0SStanley Chu UFS_EVT_DME_ERR, 49e965e5e0SStanley Chu 50e965e5e0SStanley Chu /* fatal errors */ 51e965e5e0SStanley Chu UFS_EVT_AUTO_HIBERN8_ERR, 52e965e5e0SStanley Chu UFS_EVT_FATAL_ERR, 53e965e5e0SStanley Chu UFS_EVT_LINK_STARTUP_FAIL, 54e965e5e0SStanley Chu UFS_EVT_RESUME_ERR, 55e965e5e0SStanley Chu UFS_EVT_SUSPEND_ERR, 56b294ff3eSAsutosh Das UFS_EVT_WL_SUSP_ERR, 57b294ff3eSAsutosh Das UFS_EVT_WL_RES_ERR, 58e965e5e0SStanley Chu 59e965e5e0SStanley Chu /* abnormal events */ 60e965e5e0SStanley Chu UFS_EVT_DEV_RESET, 61e965e5e0SStanley Chu UFS_EVT_HOST_RESET, 62e965e5e0SStanley Chu UFS_EVT_ABORT, 63e965e5e0SStanley Chu 64e965e5e0SStanley Chu UFS_EVT_CNT, 65e965e5e0SStanley Chu }; 66e965e5e0SStanley Chu 67e0eca63eSVinayak Holikatti /** 68e0eca63eSVinayak Holikatti * struct uic_command - UIC command structure 69e0eca63eSVinayak Holikatti * @command: UIC command 70e0eca63eSVinayak Holikatti * @argument1: UIC command argument 1 71e0eca63eSVinayak Holikatti * @argument2: UIC command argument 2 72e0eca63eSVinayak Holikatti * @argument3: UIC command argument 3 730f52fcb9SCan Guo * @cmd_active: Indicate if UIC command is outstanding 746ccf44feSSeungwon Jeon * @done: UIC command completion 75e0eca63eSVinayak Holikatti */ 76e0eca63eSVinayak Holikatti struct uic_command { 7793ef12d9SBart Van Assche const u32 command; 7893ef12d9SBart Van Assche const u32 argument1; 79e0eca63eSVinayak Holikatti u32 argument2; 80e0eca63eSVinayak Holikatti u32 argument3; 810f52fcb9SCan Guo int cmd_active; 826ccf44feSSeungwon Jeon struct completion done; 83e0eca63eSVinayak Holikatti }; 84e0eca63eSVinayak Holikatti 8557d104c1SSubhash Jadavani /* Used to differentiate the power management options */ 8657d104c1SSubhash Jadavani enum ufs_pm_op { 8757d104c1SSubhash Jadavani UFS_RUNTIME_PM, 8857d104c1SSubhash Jadavani UFS_SYSTEM_PM, 8957d104c1SSubhash Jadavani UFS_SHUTDOWN_PM, 9057d104c1SSubhash Jadavani }; 9157d104c1SSubhash Jadavani 9257d104c1SSubhash Jadavani /* Host <-> Device UniPro Link state */ 9357d104c1SSubhash Jadavani enum uic_link_state { 9457d104c1SSubhash Jadavani UIC_LINK_OFF_STATE = 0, /* Link powered down or disabled */ 9557d104c1SSubhash Jadavani UIC_LINK_ACTIVE_STATE = 1, /* Link is in Fast/Slow/Sleep state */ 9657d104c1SSubhash Jadavani UIC_LINK_HIBERN8_STATE = 2, /* Link is in Hibernate state */ 974db7a236SCan Guo UIC_LINK_BROKEN_STATE = 3, /* Link is in broken state */ 9857d104c1SSubhash Jadavani }; 9957d104c1SSubhash Jadavani 10057d104c1SSubhash Jadavani #define ufshcd_is_link_off(hba) ((hba)->uic_link_state == UIC_LINK_OFF_STATE) 10157d104c1SSubhash Jadavani #define ufshcd_is_link_active(hba) ((hba)->uic_link_state == \ 10257d104c1SSubhash Jadavani UIC_LINK_ACTIVE_STATE) 10357d104c1SSubhash Jadavani #define ufshcd_is_link_hibern8(hba) ((hba)->uic_link_state == \ 10457d104c1SSubhash Jadavani UIC_LINK_HIBERN8_STATE) 1054db7a236SCan Guo #define ufshcd_is_link_broken(hba) ((hba)->uic_link_state == \ 1064db7a236SCan Guo UIC_LINK_BROKEN_STATE) 10757d104c1SSubhash Jadavani #define ufshcd_set_link_off(hba) ((hba)->uic_link_state = UIC_LINK_OFF_STATE) 10857d104c1SSubhash Jadavani #define ufshcd_set_link_active(hba) ((hba)->uic_link_state = \ 10957d104c1SSubhash Jadavani UIC_LINK_ACTIVE_STATE) 11057d104c1SSubhash Jadavani #define ufshcd_set_link_hibern8(hba) ((hba)->uic_link_state = \ 11157d104c1SSubhash Jadavani UIC_LINK_HIBERN8_STATE) 1124db7a236SCan Guo #define ufshcd_set_link_broken(hba) ((hba)->uic_link_state = \ 1134db7a236SCan Guo UIC_LINK_BROKEN_STATE) 11457d104c1SSubhash Jadavani 1151764fa2aSStanley Chu #define ufshcd_set_ufs_dev_active(h) \ 1161764fa2aSStanley Chu ((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE) 1171764fa2aSStanley Chu #define ufshcd_set_ufs_dev_sleep(h) \ 1181764fa2aSStanley Chu ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE) 1191764fa2aSStanley Chu #define ufshcd_set_ufs_dev_poweroff(h) \ 1201764fa2aSStanley Chu ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE) 121fe1d4c2eSAdrian Hunter #define ufshcd_set_ufs_dev_deepsleep(h) \ 122fe1d4c2eSAdrian Hunter ((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE) 1231764fa2aSStanley Chu #define ufshcd_is_ufs_dev_active(h) \ 1241764fa2aSStanley Chu ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE) 1251764fa2aSStanley Chu #define ufshcd_is_ufs_dev_sleep(h) \ 1261764fa2aSStanley Chu ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE) 1271764fa2aSStanley Chu #define ufshcd_is_ufs_dev_poweroff(h) \ 1281764fa2aSStanley Chu ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) 129fe1d4c2eSAdrian Hunter #define ufshcd_is_ufs_dev_deepsleep(h) \ 130fe1d4c2eSAdrian Hunter ((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE) 1311764fa2aSStanley Chu 13257d104c1SSubhash Jadavani /* 13357d104c1SSubhash Jadavani * UFS Power management levels. 134fe1d4c2eSAdrian Hunter * Each level is in increasing order of power savings, except DeepSleep 135fe1d4c2eSAdrian Hunter * which is lower than PowerDown with power on but not PowerDown with 136fe1d4c2eSAdrian Hunter * power off. 13757d104c1SSubhash Jadavani */ 13857d104c1SSubhash Jadavani enum ufs_pm_level { 139e2ac7ab2SBart Van Assche UFS_PM_LVL_0, 140e2ac7ab2SBart Van Assche UFS_PM_LVL_1, 141e2ac7ab2SBart Van Assche UFS_PM_LVL_2, 142e2ac7ab2SBart Van Assche UFS_PM_LVL_3, 143e2ac7ab2SBart Van Assche UFS_PM_LVL_4, 144e2ac7ab2SBart Van Assche UFS_PM_LVL_5, 145e2ac7ab2SBart Van Assche UFS_PM_LVL_6, 14657d104c1SSubhash Jadavani UFS_PM_LVL_MAX 14757d104c1SSubhash Jadavani }; 14857d104c1SSubhash Jadavani 14957d104c1SSubhash Jadavani struct ufs_pm_lvl_states { 15057d104c1SSubhash Jadavani enum ufs_dev_pwr_mode dev_state; 15157d104c1SSubhash Jadavani enum uic_link_state link_state; 15257d104c1SSubhash Jadavani }; 15357d104c1SSubhash Jadavani 154e0eca63eSVinayak Holikatti /** 155e0eca63eSVinayak Holikatti * struct ufshcd_lrb - local reference block 156e0eca63eSVinayak Holikatti * @utr_descriptor_ptr: UTRD address of the command 1575a0b0cb9SSujit Reddy Thumma * @ucd_req_ptr: UCD address of the command 158e0eca63eSVinayak Holikatti * @ucd_rsp_ptr: Response UPIU address for this command 159e0eca63eSVinayak Holikatti * @ucd_prdt_ptr: PRDT address of the command 160ff8e20c6SDolev Raviv * @utrd_dma_addr: UTRD dma address for debug 161ff8e20c6SDolev Raviv * @ucd_prdt_dma_addr: PRDT dma address for debug 162ff8e20c6SDolev Raviv * @ucd_rsp_dma_addr: UPIU response dma address for debug 163ff8e20c6SDolev Raviv * @ucd_req_dma_addr: UPIU request dma address for debug 164e0eca63eSVinayak Holikatti * @cmd: pointer to SCSI command 165e0eca63eSVinayak Holikatti * @scsi_status: SCSI status of the command 166e0eca63eSVinayak Holikatti * @command_type: SCSI, UFS, Query. 167e0eca63eSVinayak Holikatti * @task_tag: Task tag of the command 168e0eca63eSVinayak Holikatti * @lun: LUN of the command 1695a0b0cb9SSujit Reddy Thumma * @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation) 1700f85e747SDaniil Lunev * @issue_time_stamp: time stamp for debug purposes (CLOCK_MONOTONIC) 1710f85e747SDaniil Lunev * @issue_time_stamp_local_clock: time stamp for debug purposes (local_clock) 1720f85e747SDaniil Lunev * @compl_time_stamp: time stamp for statistics (CLOCK_MONOTONIC) 1730f85e747SDaniil Lunev * @compl_time_stamp_local_clock: time stamp for debug purposes (local_clock) 174df043c74SSatya Tangirala * @crypto_key_slot: the key slot to use for inline crypto (-1 if none) 175df043c74SSatya Tangirala * @data_unit_num: the data unit number for the first block for inline crypto 176e0b299e3SGilad Broner * @req_abort_skip: skip request abort task flag 177e0eca63eSVinayak Holikatti */ 178e0eca63eSVinayak Holikatti struct ufshcd_lrb { 179e0eca63eSVinayak Holikatti struct utp_transfer_req_desc *utr_descriptor_ptr; 1805a0b0cb9SSujit Reddy Thumma struct utp_upiu_req *ucd_req_ptr; 181e0eca63eSVinayak Holikatti struct utp_upiu_rsp *ucd_rsp_ptr; 182e0eca63eSVinayak Holikatti struct ufshcd_sg_entry *ucd_prdt_ptr; 183e0eca63eSVinayak Holikatti 184ff8e20c6SDolev Raviv dma_addr_t utrd_dma_addr; 185ff8e20c6SDolev Raviv dma_addr_t ucd_req_dma_addr; 186ff8e20c6SDolev Raviv dma_addr_t ucd_rsp_dma_addr; 187ff8e20c6SDolev Raviv dma_addr_t ucd_prdt_dma_addr; 188ff8e20c6SDolev Raviv 189e0eca63eSVinayak Holikatti struct scsi_cmnd *cmd; 190e0eca63eSVinayak Holikatti int scsi_status; 191e0eca63eSVinayak Holikatti 192e0eca63eSVinayak Holikatti int command_type; 193e0eca63eSVinayak Holikatti int task_tag; 1940ce147d4SSubhash Jadavani u8 lun; /* UPIU LUN id field is only 8-bit wide */ 1955a0b0cb9SSujit Reddy Thumma bool intr_cmd; 196ff8e20c6SDolev Raviv ktime_t issue_time_stamp; 1970f85e747SDaniil Lunev u64 issue_time_stamp_local_clock; 19809017188SZang Leigang ktime_t compl_time_stamp; 1990f85e747SDaniil Lunev u64 compl_time_stamp_local_clock; 200df043c74SSatya Tangirala #ifdef CONFIG_SCSI_UFS_CRYPTO 201df043c74SSatya Tangirala int crypto_key_slot; 202df043c74SSatya Tangirala u64 data_unit_num; 203df043c74SSatya Tangirala #endif 204e0b299e3SGilad Broner 205e0b299e3SGilad Broner bool req_abort_skip; 206e0eca63eSVinayak Holikatti }; 207e0eca63eSVinayak Holikatti 2085a0b0cb9SSujit Reddy Thumma /** 209e2566e0bSBart Van Assche * struct ufs_query_req - parameters for building a query request 210e2566e0bSBart Van Assche * @query_func: UPIU header query function 211e2566e0bSBart Van Assche * @upiu_req: the query request data 212e2566e0bSBart Van Assche */ 213e2566e0bSBart Van Assche struct ufs_query_req { 214e2566e0bSBart Van Assche u8 query_func; 215e2566e0bSBart Van Assche struct utp_upiu_query upiu_req; 216e2566e0bSBart Van Assche }; 217e2566e0bSBart Van Assche 218e2566e0bSBart Van Assche /** 219e2566e0bSBart Van Assche * struct ufs_query_resp - UPIU QUERY 220e2566e0bSBart Van Assche * @response: device response code 221e2566e0bSBart Van Assche * @upiu_res: query response data 222e2566e0bSBart Van Assche */ 223e2566e0bSBart Van Assche struct ufs_query_res { 224e2566e0bSBart Van Assche struct utp_upiu_query upiu_res; 225e2566e0bSBart Van Assche }; 226e2566e0bSBart Van Assche 227e2566e0bSBart Van Assche /** 228a230c2f6STomas Winkler * struct ufs_query - holds relevant data structures for query request 22968078d5cSDolev Raviv * @request: request upiu and function 23068078d5cSDolev Raviv * @descriptor: buffer for sending/receiving descriptor 23168078d5cSDolev Raviv * @response: response upiu and response 23268078d5cSDolev Raviv */ 23368078d5cSDolev Raviv struct ufs_query { 23468078d5cSDolev Raviv struct ufs_query_req request; 23568078d5cSDolev Raviv u8 *descriptor; 23668078d5cSDolev Raviv struct ufs_query_res response; 23768078d5cSDolev Raviv }; 23868078d5cSDolev Raviv 23968078d5cSDolev Raviv /** 2405a0b0cb9SSujit Reddy Thumma * struct ufs_dev_cmd - all assosiated fields with device management commands 2415a0b0cb9SSujit Reddy Thumma * @type: device management command type - Query, NOP OUT 2425a0b0cb9SSujit Reddy Thumma * @lock: lock to allow one command at a time 2435a0b0cb9SSujit Reddy Thumma * @complete: internal commands completion 244cff91dafSBart Van Assche * @query: Device management query information 2455a0b0cb9SSujit Reddy Thumma */ 2465a0b0cb9SSujit Reddy Thumma struct ufs_dev_cmd { 2475a0b0cb9SSujit Reddy Thumma enum dev_cmd_type type; 2485a0b0cb9SSujit Reddy Thumma struct mutex lock; 2495a0b0cb9SSujit Reddy Thumma struct completion *complete; 25068078d5cSDolev Raviv struct ufs_query query; 2515a0b0cb9SSujit Reddy Thumma }; 252e0eca63eSVinayak Holikatti 253c6e79dacSSujit Reddy Thumma /** 254c6e79dacSSujit Reddy Thumma * struct ufs_clk_info - UFS clock related info 255c6e79dacSSujit Reddy Thumma * @list: list headed by hba->clk_list_head 256c6e79dacSSujit Reddy Thumma * @clk: clock node 257c6e79dacSSujit Reddy Thumma * @name: clock name 258c6e79dacSSujit Reddy Thumma * @max_freq: maximum frequency supported by the clock 2594cff6d99SSahitya Tummala * @min_freq: min frequency that can be used for clock scaling 260856b3483SSahitya Tummala * @curr_freq: indicates the current frequency that it is set to 26181309c24SCan Guo * @keep_link_active: indicates that the clk should not be disabled if 262cff91dafSBart Van Assche * link is active 263c6e79dacSSujit Reddy Thumma * @enabled: variable to check against multiple enable/disable 264c6e79dacSSujit Reddy Thumma */ 265c6e79dacSSujit Reddy Thumma struct ufs_clk_info { 266c6e79dacSSujit Reddy Thumma struct list_head list; 267c6e79dacSSujit Reddy Thumma struct clk *clk; 268c6e79dacSSujit Reddy Thumma const char *name; 269c6e79dacSSujit Reddy Thumma u32 max_freq; 2704cff6d99SSahitya Tummala u32 min_freq; 271856b3483SSahitya Tummala u32 curr_freq; 27281309c24SCan Guo bool keep_link_active; 273c6e79dacSSujit Reddy Thumma bool enabled; 274c6e79dacSSujit Reddy Thumma }; 275c6e79dacSSujit Reddy Thumma 276f06fcc71SYaniv Gardi enum ufs_notify_change_status { 277f06fcc71SYaniv Gardi PRE_CHANGE, 278f06fcc71SYaniv Gardi POST_CHANGE, 279f06fcc71SYaniv Gardi }; 2807eb584dbSDolev Raviv 2817eb584dbSDolev Raviv struct ufs_pa_layer_attr { 2827eb584dbSDolev Raviv u32 gear_rx; 2837eb584dbSDolev Raviv u32 gear_tx; 2847eb584dbSDolev Raviv u32 lane_rx; 2857eb584dbSDolev Raviv u32 lane_tx; 2867eb584dbSDolev Raviv u32 pwr_rx; 2877eb584dbSDolev Raviv u32 pwr_tx; 2887eb584dbSDolev Raviv u32 hs_rate; 2897eb584dbSDolev Raviv }; 2907eb584dbSDolev Raviv 2917eb584dbSDolev Raviv struct ufs_pwr_mode_info { 2927eb584dbSDolev Raviv bool is_valid; 2937eb584dbSDolev Raviv struct ufs_pa_layer_attr info; 2947eb584dbSDolev Raviv }; 2957eb584dbSDolev Raviv 2965c0c28a8SSujit Reddy Thumma /** 2975c0c28a8SSujit Reddy Thumma * struct ufs_hba_variant_ops - variant specific callbacks 2985c0c28a8SSujit Reddy Thumma * @name: variant name 299e75ff633SAvri Altman * @max_num_rtt: maximum RTT supported by the host 3005c0c28a8SSujit Reddy Thumma * @init: called when the driver is initialized 3015c0c28a8SSujit Reddy Thumma * @exit: called to cleanup everything done in init 30278bc671bSBart Van Assche * @set_dma_mask: For setting another DMA mask than indicated by the 64AS 30378bc671bSBart Van Assche * capability bit. 3049949e702SYaniv Gardi * @get_ufs_hci_version: called to get UFS HCI version 305856b3483SSahitya Tummala * @clk_scale_notify: notifies that clks are scaled up/down 3065c0c28a8SSujit Reddy Thumma * @setup_clocks: called before touching any of the controller registers 3075c0c28a8SSujit Reddy Thumma * @hce_enable_notify: called before and after HCE enable bit is set to allow 3085c0c28a8SSujit Reddy Thumma * variant specific Uni-Pro initialization. 3095c0c28a8SSujit Reddy Thumma * @link_startup_notify: called before and after Link startup is carried out 3105c0c28a8SSujit Reddy Thumma * to allow variant specific Uni-Pro initialization. 3117eb584dbSDolev Raviv * @pwr_change_notify: called before and after a power mode change 3127eb584dbSDolev Raviv * is carried out to allow vendor spesific capabilities 3137f45ed5fSPeter Wang * to be set. PRE_CHANGE can modify final_params based 3147f45ed5fSPeter Wang * on desired_pwr_mode, but POST_CHANGE must not alter 3157f45ed5fSPeter Wang * the final_params parameter 3160e675efaSKiwoong Kim * @setup_xfer_req: called before any transfer request is issued 3170e675efaSKiwoong Kim * to set some things 318d2877be4SKiwoong Kim * @setup_task_mgmt: called before any task management request is issued 319d2877be4SKiwoong Kim * to set some things 320ee32c909SKiwoong Kim * @hibern8_notify: called around hibern8 enter/exit 32156d4a186SSubhash Jadavani * @apply_dev_quirks: called to apply device specific quirks 322cff91dafSBart Van Assche * @fixup_dev_quirks: called to modify device specific quirks 32357d104c1SSubhash Jadavani * @suspend: called during host controller PM callback 32457d104c1SSubhash Jadavani * @resume: called during host controller PM callback 3256e3fd44dSYaniv Gardi * @dbg_register_dump: used to dump controller debug information 3264b9ffb5aSJoao Pinto * @phy_initialization: used to initialize phys 327d8d9f793SBjorn Andersson * @device_reset: called to issue a reset pulse on the UFS device 328cff91dafSBart Van Assche * @config_scaling_param: called to configure clock scaling parameters 3298ecea3daSEric Biggers * @fill_crypto_prdt: initialize crypto-related fields in the PRDT 330172614a9SStanley Chu * @event_notify: called to notify important events 331c263b4efSAsutosh Das * @mcq_config_resource: called to configure MCQ platform resources 332af568c7eSBart Van Assche * @get_hba_mac: reports maximum number of outstanding commands supported by 333af568c7eSBart Van Assche * the controller. Should be implemented for UFSHCI 4.0 or later 334af568c7eSBart Van Assche * controllers that are not compliant with the UFSHCI 4.0 specification. 3352468da61SAsutosh Das * @op_runtime_config: called to config Operation and runtime regs Pointers 336f87b2c41SAsutosh Das * @get_outstanding_cqs: called to get outstanding completion queues 337edb0db05SCan Guo * @config_esi: called to config Event Specific Interrupt 338db06ae7cSPeter Wang * @config_scsi_dev: called to configure SCSI device parameters 339*d7bead60SCan Guo * @freq_to_gear_speed: called to map clock frequency to the max supported gear speed 3405c0c28a8SSujit Reddy Thumma */ 3415c0c28a8SSujit Reddy Thumma struct ufs_hba_variant_ops { 3425c0c28a8SSujit Reddy Thumma const char *name; 343e75ff633SAvri Altman int max_num_rtt; 3445c0c28a8SSujit Reddy Thumma int (*init)(struct ufs_hba *); 3455c0c28a8SSujit Reddy Thumma void (*exit)(struct ufs_hba *); 3469949e702SYaniv Gardi u32 (*get_ufs_hci_version)(struct ufs_hba *); 34778bc671bSBart Van Assche int (*set_dma_mask)(struct ufs_hba *); 3485e011fccSCan Guo int (*clk_scale_notify)(struct ufs_hba *, bool, unsigned long, 349f06fcc71SYaniv Gardi enum ufs_notify_change_status); 3501e879e8fSSubhash Jadavani int (*setup_clocks)(struct ufs_hba *, bool, 3511e879e8fSSubhash Jadavani enum ufs_notify_change_status); 352f06fcc71SYaniv Gardi int (*hce_enable_notify)(struct ufs_hba *, 353f06fcc71SYaniv Gardi enum ufs_notify_change_status); 354f06fcc71SYaniv Gardi int (*link_startup_notify)(struct ufs_hba *, 355f06fcc71SYaniv Gardi enum ufs_notify_change_status); 3567eb584dbSDolev Raviv int (*pwr_change_notify)(struct ufs_hba *, 357f06fcc71SYaniv Gardi enum ufs_notify_change_status status, 3587f45ed5fSPeter Wang struct ufs_pa_layer_attr *desired_pwr_mode, 3597f45ed5fSPeter Wang struct ufs_pa_layer_attr *final_params); 360b427609eSBart Van Assche void (*setup_xfer_req)(struct ufs_hba *hba, int tag, 361b427609eSBart Van Assche bool is_scsi_cmd); 362d2877be4SKiwoong Kim void (*setup_task_mgmt)(struct ufs_hba *, int, u8); 363ee32c909SKiwoong Kim void (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme, 364ee32c909SKiwoong Kim enum ufs_notify_change_status); 36509750066SBean Huo int (*apply_dev_quirks)(struct ufs_hba *hba); 366c28c00baSStanley Chu void (*fixup_dev_quirks)(struct ufs_hba *hba); 3679561f584SPeter Wang int (*suspend)(struct ufs_hba *, enum ufs_pm_op, 3689561f584SPeter Wang enum ufs_notify_change_status); 36957d104c1SSubhash Jadavani int (*resume)(struct ufs_hba *, enum ufs_pm_op); 3706e3fd44dSYaniv Gardi void (*dbg_register_dump)(struct ufs_hba *hba); 3714b9ffb5aSJoao Pinto int (*phy_initialization)(struct ufs_hba *); 372151f1b66SAdrian Hunter int (*device_reset)(struct ufs_hba *hba); 3732c75f9a5SAsutosh Das void (*config_scaling_param)(struct ufs_hba *hba, 3742c75f9a5SAsutosh Das struct devfreq_dev_profile *profile, 375c906e832SBart Van Assche struct devfreq_simple_ondemand_data *data); 3768ecea3daSEric Biggers int (*fill_crypto_prdt)(struct ufs_hba *hba, 3778ecea3daSEric Biggers const struct bio_crypt_ctx *crypt_ctx, 3788ecea3daSEric Biggers void *prdt, unsigned int num_segments); 379172614a9SStanley Chu void (*event_notify)(struct ufs_hba *hba, 380172614a9SStanley Chu enum ufs_event_type evt, void *data); 381c263b4efSAsutosh Das int (*mcq_config_resource)(struct ufs_hba *hba); 3827224c806SAsutosh Das int (*get_hba_mac)(struct ufs_hba *hba); 3832468da61SAsutosh Das int (*op_runtime_config)(struct ufs_hba *hba); 384f87b2c41SAsutosh Das int (*get_outstanding_cqs)(struct ufs_hba *hba, 385f87b2c41SAsutosh Das unsigned long *ocqs); 386edb0db05SCan Guo int (*config_esi)(struct ufs_hba *hba); 3877670e74fSEd Tsai void (*config_scsi_dev)(struct scsi_device *sdev); 388*d7bead60SCan Guo u32 (*freq_to_gear_speed)(struct ufs_hba *hba, unsigned long freq); 3895c0c28a8SSujit Reddy Thumma }; 3905c0c28a8SSujit Reddy Thumma 3911ab27c9cSSahitya Tummala /* clock gating state */ 3921ab27c9cSSahitya Tummala enum clk_gating_state { 3931ab27c9cSSahitya Tummala CLKS_OFF, 3941ab27c9cSSahitya Tummala CLKS_ON, 3951ab27c9cSSahitya Tummala REQ_CLKS_OFF, 3961ab27c9cSSahitya Tummala REQ_CLKS_ON, 3971ab27c9cSSahitya Tummala }; 3981ab27c9cSSahitya Tummala 3991ab27c9cSSahitya Tummala /** 4001ab27c9cSSahitya Tummala * struct ufs_clk_gating - UFS clock gating related info 4011ab27c9cSSahitya Tummala * @gate_work: worker to turn off clocks after some delay as specified in 4021ab27c9cSSahitya Tummala * delay_ms 4031ab27c9cSSahitya Tummala * @ungate_work: worker to turn on clocks that will be used in case of 4041ab27c9cSSahitya Tummala * interrupt context 405209f4e43SAvri Altman * @clk_gating_workq: workqueue for clock gating work. 406209f4e43SAvri Altman * @lock: serialize access to some struct ufs_clk_gating members. An outer lock 407209f4e43SAvri Altman * relative to the host lock 4081ab27c9cSSahitya Tummala * @state: the current clocks state 4091ab27c9cSSahitya Tummala * @delay_ms: gating delay in ms 4101ab27c9cSSahitya Tummala * @is_suspended: clk gating is suspended when set to 1 which can be used 4111ab27c9cSSahitya Tummala * during suspend/resume 4121ab27c9cSSahitya Tummala * @delay_attr: sysfs attribute to control delay_attr 413b427411aSSahitya Tummala * @enable_attr: sysfs attribute to enable/disable clock gating 414b427411aSSahitya Tummala * @is_enabled: Indicates the current status of clock gating 4154543d9d7SCan Guo * @is_initialized: Indicates whether clock gating is initialized or not 4161ab27c9cSSahitya Tummala * @active_reqs: number of requests that are pending and should be waited for 4171ab27c9cSSahitya Tummala * completion before gating clocks. 4181ab27c9cSSahitya Tummala */ 4191ab27c9cSSahitya Tummala struct ufs_clk_gating { 4201ab27c9cSSahitya Tummala struct delayed_work gate_work; 4211ab27c9cSSahitya Tummala struct work_struct ungate_work; 422209f4e43SAvri Altman struct workqueue_struct *clk_gating_workq; 423209f4e43SAvri Altman 424209f4e43SAvri Altman spinlock_t lock; 425209f4e43SAvri Altman 4261ab27c9cSSahitya Tummala enum clk_gating_state state; 4271ab27c9cSSahitya Tummala unsigned long delay_ms; 4281ab27c9cSSahitya Tummala bool is_suspended; 4291ab27c9cSSahitya Tummala struct device_attribute delay_attr; 430b427411aSSahitya Tummala struct device_attribute enable_attr; 431b427411aSSahitya Tummala bool is_enabled; 4324543d9d7SCan Guo bool is_initialized; 4331ab27c9cSSahitya Tummala int active_reqs; 4341ab27c9cSSahitya Tummala }; 4351ab27c9cSSahitya Tummala 436401f1e44Ssubhashj@codeaurora.org /** 437401f1e44Ssubhashj@codeaurora.org * struct ufs_clk_scaling - UFS clock scaling related data 438be769e5cSAvri Altman * @workq: workqueue to schedule devfreq suspend/resume work 439be769e5cSAvri Altman * @suspend_work: worker to suspend devfreq 440be769e5cSAvri Altman * @resume_work: worker to resume devfreq 441be769e5cSAvri Altman * @lock: serialize access to some struct ufs_clk_scaling members 442401f1e44Ssubhashj@codeaurora.org * @active_reqs: number of requests that are pending. If this is zero when 443401f1e44Ssubhashj@codeaurora.org * devfreq ->target() function is called then schedule "suspend_work" to 444401f1e44Ssubhashj@codeaurora.org * suspend devfreq. 445401f1e44Ssubhashj@codeaurora.org * @tot_busy_t: Total busy time in current polling window 446401f1e44Ssubhashj@codeaurora.org * @window_start_t: Start time (in jiffies) of the current polling window 447401f1e44Ssubhashj@codeaurora.org * @busy_start_t: Start time of current busy period 448401f1e44Ssubhashj@codeaurora.org * @enable_attr: sysfs attribute to enable/disable clock scaling 449401f1e44Ssubhashj@codeaurora.org * @saved_pwr_info: UFS power mode may also be changed during scaling and this 450401f1e44Ssubhashj@codeaurora.org * one keeps track of previous power mode. 451930bd77eSManivannan Sadhasivam * @target_freq: frequency requested by devfreq framework 45229b87e92SCan Guo * @min_gear: lowest HS gear to scale down to 4530e9d4ca4SCan Guo * @is_enabled: tracks if scaling is currently enabled or not, controlled by 454cff91dafSBart Van Assche * clkscale_enable sysfs node 4550e9d4ca4SCan Guo * @is_allowed: tracks if scaling is currently allowed or not, used to block 456cff91dafSBart Van Assche * clock scaling which is not invoked from devfreq governor 4574543d9d7SCan Guo * @is_initialized: Indicates whether clock scaling is initialized or not 458401f1e44Ssubhashj@codeaurora.org * @is_busy_started: tracks if busy period has started or not 459401f1e44Ssubhashj@codeaurora.org * @is_suspended: tracks if devfreq is suspended or not 460401f1e44Ssubhashj@codeaurora.org */ 461856b3483SSahitya Tummala struct ufs_clk_scaling { 462be769e5cSAvri Altman struct workqueue_struct *workq; 463be769e5cSAvri Altman struct work_struct suspend_work; 464be769e5cSAvri Altman struct work_struct resume_work; 465be769e5cSAvri Altman 466be769e5cSAvri Altman spinlock_t lock; 467be769e5cSAvri Altman 468401f1e44Ssubhashj@codeaurora.org int active_reqs; 469856b3483SSahitya Tummala unsigned long tot_busy_t; 470b1bf66d1SStanley Chu ktime_t window_start_t; 471401f1e44Ssubhashj@codeaurora.org ktime_t busy_start_t; 472fcb0c4b0SSahitya Tummala struct device_attribute enable_attr; 473543a827bSStanley Chu struct ufs_pa_layer_attr saved_pwr_info; 474930bd77eSManivannan Sadhasivam unsigned long target_freq; 47529b87e92SCan Guo u32 min_gear; 4760e9d4ca4SCan Guo bool is_enabled; 477401f1e44Ssubhashj@codeaurora.org bool is_allowed; 4784543d9d7SCan Guo bool is_initialized; 479401f1e44Ssubhashj@codeaurora.org bool is_busy_started; 480401f1e44Ssubhashj@codeaurora.org bool is_suspended; 48150183ac2SRam Prakash Gupta bool suspend_on_no_request; 482856b3483SSahitya Tummala }; 483856b3483SSahitya Tummala 484e965e5e0SStanley Chu #define UFS_EVENT_HIST_LENGTH 8 485ff8e20c6SDolev Raviv /** 486e965e5e0SStanley Chu * struct ufs_event_hist - keeps history of errors 487ff8e20c6SDolev Raviv * @pos: index to indicate cyclic buffer position 488cff91dafSBart Van Assche * @val: cyclic buffer for registers value 489ff8e20c6SDolev Raviv * @tstamp: cyclic buffer for time stamp 490b6cacaf2SAdrian Hunter * @cnt: error counter 491ff8e20c6SDolev Raviv */ 492e965e5e0SStanley Chu struct ufs_event_hist { 493ff8e20c6SDolev Raviv int pos; 494e965e5e0SStanley Chu u32 val[UFS_EVENT_HIST_LENGTH]; 4950f85e747SDaniil Lunev u64 tstamp[UFS_EVENT_HIST_LENGTH]; 496b6cacaf2SAdrian Hunter unsigned long long cnt; 497ff8e20c6SDolev Raviv }; 498ff8e20c6SDolev Raviv 499ff8e20c6SDolev Raviv /** 500ff8e20c6SDolev Raviv * struct ufs_stats - keeps usage/err statistics 5013f8af604SCan Guo * @last_intr_status: record the last interrupt status. 5023f8af604SCan Guo * @last_intr_ts: record the last interrupt timestamp. 503ff8e20c6SDolev Raviv * @hibern8_exit_cnt: Counter to keep track of number of exits, 504ff8e20c6SDolev Raviv * reset this after link-startup. 505ff8e20c6SDolev Raviv * @last_hibern8_exit_tstamp: Set time after the hibern8 exit. 506ff8e20c6SDolev Raviv * Clear after the first successful command completion. 507cff91dafSBart Van Assche * @event: array with event history. 508ff8e20c6SDolev Raviv */ 509ff8e20c6SDolev Raviv struct ufs_stats { 5103f8af604SCan Guo u32 last_intr_status; 5110f85e747SDaniil Lunev u64 last_intr_ts; 5123f8af604SCan Guo 513ff8e20c6SDolev Raviv u32 hibern8_exit_cnt; 5140f85e747SDaniil Lunev u64 last_hibern8_exit_tstamp; 515e965e5e0SStanley Chu struct ufs_event_hist event[UFS_EVT_CNT]; 516ff8e20c6SDolev Raviv }; 517ff8e20c6SDolev Raviv 5189c202090SBart Van Assche /** 5199c202090SBart Van Assche * enum ufshcd_state - UFS host controller state 5209c202090SBart Van Assche * @UFSHCD_STATE_RESET: Link is not operational. Postpone SCSI command 5219c202090SBart Van Assche * processing. 5229c202090SBart Van Assche * @UFSHCD_STATE_OPERATIONAL: The host controller is operational and can process 5239c202090SBart Van Assche * SCSI commands. 5249c202090SBart Van Assche * @UFSHCD_STATE_EH_SCHEDULED_NON_FATAL: The error handler has been scheduled. 5259c202090SBart Van Assche * SCSI commands may be submitted to the controller. 5269c202090SBart Van Assche * @UFSHCD_STATE_EH_SCHEDULED_FATAL: The error handler has been scheduled. Fail 5279c202090SBart Van Assche * newly submitted SCSI commands with error code DID_BAD_TARGET. 5289c202090SBart Van Assche * @UFSHCD_STATE_ERROR: An unrecoverable error occurred, e.g. link recovery 5299c202090SBart Van Assche * failed. Fail all SCSI commands with error code DID_ERROR. 5309c202090SBart Van Assche */ 5319c202090SBart Van Assche enum ufshcd_state { 5329c202090SBart Van Assche UFSHCD_STATE_RESET, 5339c202090SBart Van Assche UFSHCD_STATE_OPERATIONAL, 5349c202090SBart Van Assche UFSHCD_STATE_EH_SCHEDULED_NON_FATAL, 5359c202090SBart Van Assche UFSHCD_STATE_EH_SCHEDULED_FATAL, 5369c202090SBart Van Assche UFSHCD_STATE_ERROR, 5379c202090SBart Van Assche }; 5389c202090SBart Van Assche 539c3f7d1fcSChristoph Hellwig enum ufshcd_quirks { 540c3f7d1fcSChristoph Hellwig /* Interrupt aggregation support is broken */ 541c3f7d1fcSChristoph Hellwig UFSHCD_QUIRK_BROKEN_INTR_AGGR = 1 << 0, 542c3f7d1fcSChristoph Hellwig 543c3f7d1fcSChristoph Hellwig /* 544c3f7d1fcSChristoph Hellwig * delay before each dme command is required as the unipro 545c3f7d1fcSChristoph Hellwig * layer has shown instabilities 546c3f7d1fcSChristoph Hellwig */ 547c3f7d1fcSChristoph Hellwig UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS = 1 << 1, 548c3f7d1fcSChristoph Hellwig 549c3f7d1fcSChristoph Hellwig /* 550c3f7d1fcSChristoph Hellwig * If UFS host controller is having issue in processing LCC (Line 551c3f7d1fcSChristoph Hellwig * Control Command) coming from device then enable this quirk. 552c3f7d1fcSChristoph Hellwig * When this quirk is enabled, host controller driver should disable 553c3f7d1fcSChristoph Hellwig * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE 554c3f7d1fcSChristoph Hellwig * attribute of device to 0). 555c3f7d1fcSChristoph Hellwig */ 556c3f7d1fcSChristoph Hellwig UFSHCD_QUIRK_BROKEN_LCC = 1 << 2, 557c3f7d1fcSChristoph Hellwig 558c3f7d1fcSChristoph Hellwig /* 559c3f7d1fcSChristoph Hellwig * The attribute PA_RXHSUNTERMCAP specifies whether or not the 560c3f7d1fcSChristoph Hellwig * inbound Link supports unterminated line in HS mode. Setting this 561c3f7d1fcSChristoph Hellwig * attribute to 1 fixes moving to HS gear. 562c3f7d1fcSChristoph Hellwig */ 563c3f7d1fcSChristoph Hellwig UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP = 1 << 3, 564c3f7d1fcSChristoph Hellwig 565c3f7d1fcSChristoph Hellwig /* 566c3f7d1fcSChristoph Hellwig * This quirk needs to be enabled if the host controller only allows 567c3f7d1fcSChristoph Hellwig * accessing the peer dme attributes in AUTO mode (FAST AUTO or 568c3f7d1fcSChristoph Hellwig * SLOW AUTO). 569c3f7d1fcSChristoph Hellwig */ 570c3f7d1fcSChristoph Hellwig UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE = 1 << 4, 571c3f7d1fcSChristoph Hellwig 572c3f7d1fcSChristoph Hellwig /* 573c3f7d1fcSChristoph Hellwig * This quirk needs to be enabled if the host controller doesn't 574c3f7d1fcSChristoph Hellwig * advertise the correct version in UFS_VER register. If this quirk 575c3f7d1fcSChristoph Hellwig * is enabled, standard UFS host driver will call the vendor specific 576c3f7d1fcSChristoph Hellwig * ops (get_ufs_hci_version) to get the correct version. 577c3f7d1fcSChristoph Hellwig */ 578c3f7d1fcSChristoph Hellwig UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5, 57987183841SAlim Akhtar 58087183841SAlim Akhtar /* 58187183841SAlim Akhtar * Clear handling for transfer/task request list is just opposite. 58287183841SAlim Akhtar */ 58387183841SAlim Akhtar UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR = 1 << 6, 584b638b5ebSAlim Akhtar 585b638b5ebSAlim Akhtar /* 586b638b5ebSAlim Akhtar * This quirk needs to be enabled if host controller doesn't allow 587b638b5ebSAlim Akhtar * that the interrupt aggregation timer and counter are reset by s/w. 588b638b5ebSAlim Akhtar */ 589b638b5ebSAlim Akhtar UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR = 1 << 7, 59039bf2d83SAlim Akhtar 59139bf2d83SAlim Akhtar /* 59239bf2d83SAlim Akhtar * This quirks needs to be enabled if host controller cannot be 59339bf2d83SAlim Akhtar * enabled via HCE register. 59439bf2d83SAlim Akhtar */ 59539bf2d83SAlim Akhtar UFSHCI_QUIRK_BROKEN_HCE = 1 << 8, 59626f968d7SAlim Akhtar 59726f968d7SAlim Akhtar /* 59826f968d7SAlim Akhtar * This quirk needs to be enabled if the host controller regards 59926f968d7SAlim Akhtar * resolution of the values of PRDTO and PRDTL in UTRD as byte. 60026f968d7SAlim Akhtar */ 60126f968d7SAlim Akhtar UFSHCD_QUIRK_PRDT_BYTE_GRAN = 1 << 9, 602d779a6e9SKiwoong Kim 603d779a6e9SKiwoong Kim /* 604d779a6e9SKiwoong Kim * This quirk needs to be enabled if the host controller reports 605d779a6e9SKiwoong Kim * OCS FATAL ERROR with device error through sense data 606d779a6e9SKiwoong Kim */ 607d779a6e9SKiwoong Kim UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR = 1 << 10, 6085df6f2deSKiwoong Kim 6095df6f2deSKiwoong Kim /* 6108da76f71SAdrian Hunter * This quirk needs to be enabled if the host controller has 6118da76f71SAdrian Hunter * auto-hibernate capability but it doesn't work. 6128da76f71SAdrian Hunter */ 6138da76f71SAdrian Hunter UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8 = 1 << 11, 61402f74150SMartin K. Petersen 61502f74150SMartin K. Petersen /* 6165df6f2deSKiwoong Kim * This quirk needs to disable manual flush for write booster 6175df6f2deSKiwoong Kim */ 61802f74150SMartin K. Petersen UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL = 1 << 12, 61902f74150SMartin K. Petersen 620b1d0d2ebSKiwoong Kim /* 621b1d0d2ebSKiwoong Kim * This quirk needs to disable unipro timeout values 622b1d0d2ebSKiwoong Kim * before power mode change 623b1d0d2ebSKiwoong Kim */ 624b1d0d2ebSKiwoong Kim UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13, 625b1d0d2ebSKiwoong Kim 6262b2bfc8aSKiwoong Kim /* 627a22bcfdbSjongmin jeong * This quirk needs to be enabled if the host controller does not 628a22bcfdbSjongmin jeong * support UIC command 629a22bcfdbSjongmin jeong */ 630a22bcfdbSjongmin jeong UFSHCD_QUIRK_BROKEN_UIC_CMD = 1 << 15, 63110fb4f87Sjongmin jeong 63210fb4f87Sjongmin jeong /* 63310fb4f87Sjongmin jeong * This quirk needs to be enabled if the host controller cannot 63410fb4f87Sjongmin jeong * support physical host configuration. 63510fb4f87Sjongmin jeong */ 63610fb4f87Sjongmin jeong UFSHCD_QUIRK_SKIP_PH_CONFIGURATION = 1 << 16, 6376554400dSYoshihiro Shimoda 6386554400dSYoshihiro Shimoda /* 6396554400dSYoshihiro Shimoda * This quirk needs to be enabled if the host controller has 6402f11bbc2SYoshihiro Shimoda * auto-hibernate capability but it's FASTAUTO only. 6412f11bbc2SYoshihiro Shimoda */ 6422f11bbc2SYoshihiro Shimoda UFSHCD_QUIRK_HIBERN_FASTAUTO = 1 << 18, 64396a7141dSManivannan Sadhasivam 64496a7141dSManivannan Sadhasivam /* 64596a7141dSManivannan Sadhasivam * This quirk needs to be enabled if the host controller needs 64696a7141dSManivannan Sadhasivam * to reinit the device after switching to maximum gear. 64796a7141dSManivannan Sadhasivam */ 64896a7141dSManivannan Sadhasivam UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH = 1 << 19, 649c4ad4f2eSPo-Wen Kao 650c4ad4f2eSPo-Wen Kao /* 651c4ad4f2eSPo-Wen Kao * Some host raises interrupt (per queue) in addition to 652c4ad4f2eSPo-Wen Kao * CQES (traditional) when ESI is disabled. 653c4ad4f2eSPo-Wen Kao * Enable this quirk will disable CQES and use per queue interrupt. 654c4ad4f2eSPo-Wen Kao */ 655c4ad4f2eSPo-Wen Kao UFSHCD_QUIRK_MCQ_BROKEN_INTR = 1 << 20, 656aa9d5d00SPo-Wen Kao 657aa9d5d00SPo-Wen Kao /* 658aa9d5d00SPo-Wen Kao * Some host does not implement SQ Run Time Command (SQRTC) register 659aa9d5d00SPo-Wen Kao * thus need this quirk to skip related flow. 660aa9d5d00SPo-Wen Kao */ 661aa9d5d00SPo-Wen Kao UFSHCD_QUIRK_MCQ_BROKEN_RTC = 1 << 21, 662c2a90eeeSEric Biggers 663c2a90eeeSEric Biggers /* 664c2a90eeeSEric Biggers * This quirk needs to be enabled if the host controller supports inline 665c2a90eeeSEric Biggers * encryption but it needs to initialize the crypto capabilities in a 666c2a90eeeSEric Biggers * nonstandard way and/or needs to override blk_crypto_ll_ops. If 667c2a90eeeSEric Biggers * enabled, the standard code won't initialize the blk_crypto_profile; 668c2a90eeeSEric Biggers * ufs_hba_variant_ops::init() must do it instead. 669c2a90eeeSEric Biggers */ 670c2a90eeeSEric Biggers UFSHCD_QUIRK_CUSTOM_CRYPTO_PROFILE = 1 << 22, 671e95881e0SEric Biggers 672e95881e0SEric Biggers /* 673e95881e0SEric Biggers * This quirk needs to be enabled if the host controller supports inline 674e95881e0SEric Biggers * encryption but does not support the CRYPTO_GENERAL_ENABLE bit, i.e. 675e95881e0SEric Biggers * host controller initialization fails if that bit is set. 676e95881e0SEric Biggers */ 677e95881e0SEric Biggers UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE = 1 << 23, 6784c45dba5SEric Biggers 6794c45dba5SEric Biggers /* 6804c45dba5SEric Biggers * This quirk needs to be enabled if the host controller driver copies 6814c45dba5SEric Biggers * cryptographic keys into the PRDT in order to send them to hardware, 6824c45dba5SEric Biggers * and therefore the PRDT should be zeroized after each request (as per 6834c45dba5SEric Biggers * the standard best practice for managing keys). 6844c45dba5SEric Biggers */ 6854c45dba5SEric Biggers UFSHCD_QUIRK_KEYS_IN_PRDT = 1 << 24, 686cd06b713SManivannan Sadhasivam 687cd06b713SManivannan Sadhasivam /* 688cd06b713SManivannan Sadhasivam * This quirk indicates that the controller reports the value 1 (not 689cd06b713SManivannan Sadhasivam * supported) in the Legacy Single DoorBell Support (LSDBS) bit of the 690cd06b713SManivannan Sadhasivam * Controller Capabilities register although it supports the legacy 691cd06b713SManivannan Sadhasivam * single doorbell mode. 692cd06b713SManivannan Sadhasivam */ 693cd06b713SManivannan Sadhasivam UFSHCD_QUIRK_BROKEN_LSDBS_CAP = 1 << 25, 694c3f7d1fcSChristoph Hellwig }; 695c3f7d1fcSChristoph Hellwig 696c2014682SStanley Chu enum ufshcd_caps { 697c2014682SStanley Chu /* Allow dynamic clk gating */ 698c2014682SStanley Chu UFSHCD_CAP_CLK_GATING = 1 << 0, 699c2014682SStanley Chu 700c2014682SStanley Chu /* Allow hiberb8 with clk gating */ 701c2014682SStanley Chu UFSHCD_CAP_HIBERN8_WITH_CLK_GATING = 1 << 1, 702c2014682SStanley Chu 703c2014682SStanley Chu /* Allow dynamic clk scaling */ 704c2014682SStanley Chu UFSHCD_CAP_CLK_SCALING = 1 << 2, 705c2014682SStanley Chu 706c2014682SStanley Chu /* Allow auto bkops to enabled during runtime suspend */ 707c2014682SStanley Chu UFSHCD_CAP_AUTO_BKOPS_SUSPEND = 1 << 3, 708c2014682SStanley Chu 709c2014682SStanley Chu /* 710c2014682SStanley Chu * This capability allows host controller driver to use the UFS HCI's 711c2014682SStanley Chu * interrupt aggregation capability. 712c2014682SStanley Chu * CAUTION: Enabling this might reduce overall UFS throughput. 713c2014682SStanley Chu */ 714c2014682SStanley Chu UFSHCD_CAP_INTR_AGGR = 1 << 4, 715c2014682SStanley Chu 716c2014682SStanley Chu /* 717c2014682SStanley Chu * This capability allows the device auto-bkops to be always enabled 718c2014682SStanley Chu * except during suspend (both runtime and suspend). 719c2014682SStanley Chu * Enabling this capability means that device will always be allowed 720c2014682SStanley Chu * to do background operation when it's active but it might degrade 721c2014682SStanley Chu * the performance of ongoing read/write operations. 722c2014682SStanley Chu */ 723c2014682SStanley Chu UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND = 1 << 5, 724c2014682SStanley Chu 725c2014682SStanley Chu /* 726c2014682SStanley Chu * This capability allows host controller driver to automatically 727c2014682SStanley Chu * enable runtime power management by itself instead of waiting 728c2014682SStanley Chu * for userspace to control the power management. 729c2014682SStanley Chu */ 730c2014682SStanley Chu UFSHCD_CAP_RPM_AUTOSUSPEND = 1 << 6, 7313d17b9b5SAsutosh Das 7323d17b9b5SAsutosh Das /* 7333d17b9b5SAsutosh Das * This capability allows the host controller driver to turn-on 7343d17b9b5SAsutosh Das * WriteBooster, if the underlying device supports it and is 7353d17b9b5SAsutosh Das * provisioned to be used. This would increase the write performance. 7363d17b9b5SAsutosh Das */ 7373d17b9b5SAsutosh Das UFSHCD_CAP_WB_EN = 1 << 7, 7385e7341e1SSatya Tangirala 7395e7341e1SSatya Tangirala /* 7405e7341e1SSatya Tangirala * This capability allows the host controller driver to use the 7415e7341e1SSatya Tangirala * inline crypto engine, if it is present 7425e7341e1SSatya Tangirala */ 7435e7341e1SSatya Tangirala UFSHCD_CAP_CRYPTO = 1 << 8, 744dd7143e2SCan Guo 745dd7143e2SCan Guo /* 746dd7143e2SCan Guo * This capability allows the controller regulators to be put into 747dd7143e2SCan Guo * lpm mode aggressively during clock gating. 748dd7143e2SCan Guo * This would increase power savings. 749dd7143e2SCan Guo */ 750dd7143e2SCan Guo UFSHCD_CAP_AGGR_POWER_COLLAPSE = 1 << 9, 751fe1d4c2eSAdrian Hunter 752fe1d4c2eSAdrian Hunter /* 753fe1d4c2eSAdrian Hunter * This capability allows the host controller driver to use DeepSleep, 754fe1d4c2eSAdrian Hunter * if it is supported by the UFS device. The host controller driver must 755fe1d4c2eSAdrian Hunter * support device hardware reset via the hba->device_reset() callback, 756fe1d4c2eSAdrian Hunter * in order to exit DeepSleep state. 757fe1d4c2eSAdrian Hunter */ 758fe1d4c2eSAdrian Hunter UFSHCD_CAP_DEEPSLEEP = 1 << 10, 759e88e2d32SAvri Altman 760e88e2d32SAvri Altman /* 761e88e2d32SAvri Altman * This capability allows the host controller driver to use temperature 762e88e2d32SAvri Altman * notification if it is supported by the UFS device. 763e88e2d32SAvri Altman */ 764e88e2d32SAvri Altman UFSHCD_CAP_TEMP_NOTIF = 1 << 11, 76587bd0501SPeter Wang 76687bd0501SPeter Wang /* 76787bd0501SPeter Wang * Enable WriteBooster when scaling up the clock and disable 76887bd0501SPeter Wang * WriteBooster when scaling the clock down. 76987bd0501SPeter Wang */ 77087bd0501SPeter Wang UFSHCD_CAP_WB_WITH_CLK_SCALING = 1 << 12, 771c2014682SStanley Chu }; 772c2014682SStanley Chu 77390b8491cSStanley Chu struct ufs_hba_variant_params { 77490b8491cSStanley Chu struct devfreq_dev_profile devfreq_profile; 77590b8491cSStanley Chu struct devfreq_simple_ondemand_data ondemand_data; 77690b8491cSStanley Chu u16 hba_enable_delay_us; 777d14734aeSStanley Chu u32 wb_flush_threshold; 77890b8491cSStanley Chu }; 77990b8491cSStanley Chu 7801d8613a2SCan Guo struct ufs_hba_monitor { 7811d8613a2SCan Guo unsigned long chunk_size; 7821d8613a2SCan Guo 7831d8613a2SCan Guo unsigned long nr_sec_rw[2]; 7841d8613a2SCan Guo ktime_t total_busy[2]; 7851d8613a2SCan Guo 7861d8613a2SCan Guo unsigned long nr_req[2]; 7871d8613a2SCan Guo /* latencies*/ 7881d8613a2SCan Guo ktime_t lat_sum[2]; 7891d8613a2SCan Guo ktime_t lat_max[2]; 7901d8613a2SCan Guo ktime_t lat_min[2]; 7911d8613a2SCan Guo 7921d8613a2SCan Guo u32 nr_queued[2]; 7931d8613a2SCan Guo ktime_t busy_start_ts[2]; 7941d8613a2SCan Guo 7951d8613a2SCan Guo ktime_t enabled_ts; 7961d8613a2SCan Guo bool enabled; 7971d8613a2SCan Guo }; 7981d8613a2SCan Guo 7993a4bf06dSYaniv Gardi /** 800c263b4efSAsutosh Das * struct ufshcd_res_info_t - MCQ related resource regions 801c263b4efSAsutosh Das * 802c263b4efSAsutosh Das * @name: resource name 803c263b4efSAsutosh Das * @resource: pointer to resource region 804c263b4efSAsutosh Das * @base: register base address 805c263b4efSAsutosh Das */ 806c263b4efSAsutosh Das struct ufshcd_res_info { 807c263b4efSAsutosh Das const char *name; 808c263b4efSAsutosh Das struct resource *resource; 809c263b4efSAsutosh Das void __iomem *base; 810c263b4efSAsutosh Das }; 811c263b4efSAsutosh Das 812c263b4efSAsutosh Das enum ufshcd_res { 813c263b4efSAsutosh Das RES_UFS, 814c263b4efSAsutosh Das RES_MCQ, 815c263b4efSAsutosh Das RES_MCQ_SQD, 816c263b4efSAsutosh Das RES_MCQ_SQIS, 817c263b4efSAsutosh Das RES_MCQ_CQD, 818c263b4efSAsutosh Das RES_MCQ_CQIS, 819c263b4efSAsutosh Das RES_MCQ_VS, 820c263b4efSAsutosh Das RES_MAX, 821c263b4efSAsutosh Das }; 822c263b4efSAsutosh Das 823c263b4efSAsutosh Das /** 8242468da61SAsutosh Das * struct ufshcd_mcq_opr_info_t - Operation and Runtime registers 8252468da61SAsutosh Das * 8262468da61SAsutosh Das * @offset: Doorbell Address Offset 8272468da61SAsutosh Das * @stride: Steps proportional to queue [0...31] 8282468da61SAsutosh Das * @base: base address 8292468da61SAsutosh Das */ 8302468da61SAsutosh Das struct ufshcd_mcq_opr_info_t { 8312468da61SAsutosh Das unsigned long offset; 8322468da61SAsutosh Das unsigned long stride; 8332468da61SAsutosh Das void __iomem *base; 8342468da61SAsutosh Das }; 8352468da61SAsutosh Das 8362468da61SAsutosh Das enum ufshcd_mcq_opr { 8372468da61SAsutosh Das OPR_SQD, 8382468da61SAsutosh Das OPR_SQIS, 8392468da61SAsutosh Das OPR_CQD, 8402468da61SAsutosh Das OPR_CQIS, 8412468da61SAsutosh Das OPR_MAX, 8422468da61SAsutosh Das }; 8432468da61SAsutosh Das 8442468da61SAsutosh Das /** 845e0eca63eSVinayak Holikatti * struct ufs_hba - per adapter private structure 846e0eca63eSVinayak Holikatti * @mmio_base: UFSHCI base register address 847e0eca63eSVinayak Holikatti * @ucdl_base_addr: UFS Command Descriptor base address 848e0eca63eSVinayak Holikatti * @utrdl_base_addr: UTP Transfer Request Descriptor base address 849e0eca63eSVinayak Holikatti * @utmrdl_base_addr: UTP Task Management Descriptor base address 850e0eca63eSVinayak Holikatti * @ucdl_dma_addr: UFS Command Descriptor DMA address 851e0eca63eSVinayak Holikatti * @utrdl_dma_addr: UTRDL DMA address 852e0eca63eSVinayak Holikatti * @utmrdl_dma_addr: UTMRDL DMA address 853e0eca63eSVinayak Holikatti * @host: Scsi_Host instance of the driver 854e0eca63eSVinayak Holikatti * @dev: device handle 855e2106584SBart Van Assche * @ufs_device_wlun: WLUN that controls the entire UFS device. 856cff91dafSBart Van Assche * @hwmon_device: device instance registered with the hwmon core. 857cff91dafSBart Van Assche * @curr_dev_pwr_mode: active UFS device power mode. 858cff91dafSBart Van Assche * @uic_link_state: active state of the link to the UFS device. 859cff91dafSBart Van Assche * @rpm_lvl: desired UFS power management level during runtime PM. 860cff91dafSBart Van Assche * @spm_lvl: desired UFS power management level during system PM. 861cff91dafSBart Van Assche * @pm_op_in_progress: whether or not a PM operation is in progress. 862cff91dafSBart Van Assche * @ahit: value of Auto-Hibernate Idle Timer register. 863e0eca63eSVinayak Holikatti * @lrb: local reference block 864e0eca63eSVinayak Holikatti * @outstanding_tasks: Bits representing outstanding task requests 865169f5eb2SBart Van Assche * @outstanding_lock: Protects @outstanding_reqs. 866e0eca63eSVinayak Holikatti * @outstanding_reqs: Bits representing outstanding transfer requests 867e0eca63eSVinayak Holikatti * @capabilities: UFS Controller Capabilities 8686e1d850aSAsutosh Das * @mcq_capabilities: UFS Multi Circular Queue capabilities 869e0eca63eSVinayak Holikatti * @nutrs: Transfer Request Queue depth supported by controller 8709ec54934SAvri Altman * @nortt - Max outstanding RTTs supported by controller 871e0eca63eSVinayak Holikatti * @nutmrs: Task Management Queue depth supported by controller 872945c3ccaSBart Van Assche * @reserved_slot: Used to submit device commands. Protected by @dev_cmd.lock. 873e0eca63eSVinayak Holikatti * @ufs_version: UFS Version to which controller complies 8745c0c28a8SSujit Reddy Thumma * @vops: pointer to variant specific operations 875cff91dafSBart Van Assche * @vps: pointer to variant specific parameters 8765c0c28a8SSujit Reddy Thumma * @priv: pointer to variant specific private data 877ada1e653SEric Biggers * @sg_entry_size: size of struct ufshcd_sg_entry (may include variant fields) 878e0eca63eSVinayak Holikatti * @irq: Irq number of the controller 879cff91dafSBart Van Assche * @is_irq_enabled: whether or not the UFS controller interrupt is enabled. 880cff91dafSBart Van Assche * @dev_ref_clk_freq: reference clock frequency 881cff91dafSBart Van Assche * @quirks: bitmask with information about deviations from the UFSHCI standard. 882cff91dafSBart Van Assche * @dev_quirks: bitmask with information about deviations from the UFS standard. 88369a6c269SBart Van Assche * @tmf_tag_set: TMF tag set. 88469a6c269SBart Van Assche * @tmf_queue: Used to allocate TMF tags. 885cff91dafSBart Van Assche * @tmf_rqs: array with pointers to TMF requests while these are in progress. 88622fbabe8SBart Van Assche * @active_uic_cmd: pointer to active UIC command. 88722fbabe8SBart Van Assche * @uic_cmd_mutex: mutex used for serializing UIC command processing. 88822fbabe8SBart Van Assche * @uic_async_done: completion used to wait for power mode or hibernation state 88922fbabe8SBart Van Assche * changes. 8909c202090SBart Van Assche * @ufshcd_state: UFSHCD state 8913441da7dSSujit Reddy Thumma * @eh_flags: Error handling flags 8922fbd009bSSeungwon Jeon * @intr_mask: Interrupt Mask Bits 89366ec6d59SSujit Reddy Thumma * @ee_ctrl_mask: Exception event control mask 894cff91dafSBart Van Assche * @ee_drv_mask: Exception event mask for driver 895cff91dafSBart Van Assche * @ee_usr_mask: Exception event mask for user (set via debugfs) 896cff91dafSBart Van Assche * @ee_ctrl_mutex: Used to serialize exception event information. 8971d337ec2SSujit Reddy Thumma * @is_powered: flag to check if HBA is powered 8989cd20d3fSCan Guo * @shutting_down: flag to check if shutdown has been invoked 8999cd20d3fSCan Guo * @host_sem: semaphore used to serialize concurrent contexts 90088b09900SAdrian Hunter * @eh_wq: Workqueue that eh_work works on 90188b09900SAdrian Hunter * @eh_work: Worker to handle UFS errors that require s/w attention 90266ec6d59SSujit Reddy Thumma * @eeh_work: Worker to handle exception events 903e0eca63eSVinayak Holikatti * @errors: HBA errors 904e8e7f271SSujit Reddy Thumma * @uic_error: UFS interconnect layer error status 905e8e7f271SSujit Reddy Thumma * @saved_err: sticky error mask 906e8e7f271SSujit Reddy Thumma * @saved_uic_err: sticky UIC error mask 907cff91dafSBart Van Assche * @ufs_stats: various error counters 9084db7a236SCan Guo * @force_reset: flag to force eh_work perform a full reset 9092355b66eSCan Guo * @force_pmc: flag to force a power mode change 9102df74b69SCan Guo * @silence_err_logs: flag to silence error logs 9115a0b0cb9SSujit Reddy Thumma * @dev_cmd: ufs device management command information 912cad2e03dSYaniv Gardi * @last_dme_cmd_tstamp: time stamp of the last completed DME command 913cff91dafSBart Van Assche * @nop_out_timeout: NOP OUT timeout value 914cff91dafSBart Van Assche * @dev_info: information about the UFS device 91566ec6d59SSujit Reddy Thumma * @auto_bkops_enabled: to track whether bkops is enabled in device 916aa497613SSujit Reddy Thumma * @vreg_info: UFS device voltage regulator information 917c6e79dacSSujit Reddy Thumma * @clk_list_head: UFS host controller clocks list node head 918930bd77eSManivannan Sadhasivam * @use_pm_opp: Indicates whether OPP based scaling is used or not 919cff91dafSBart Van Assche * @req_abort_count: number of times ufshcd_abort() has been called 920cff91dafSBart Van Assche * @lanes_per_direction: number of lanes per data direction between the UFS 921cff91dafSBart Van Assche * controller and the UFS device. 9227eb584dbSDolev Raviv * @pwr_info: holds current power mode 9237eb584dbSDolev Raviv * @max_pwr_info: keeps the device max valid pwm 924cff91dafSBart Van Assche * @clk_gating: information related to clock gating 925cff91dafSBart Van Assche * @caps: bitmask with information about UFS controller capabilities 926cff91dafSBart Van Assche * @devfreq: frequency scaling information owned by the devfreq core 927cff91dafSBart Van Assche * @clk_scaling: frequency scaling information owned by the UFS driver 9281a547cbcSBart Van Assche * @system_suspending: system suspend has been started and system resume has 9291a547cbcSBart Van Assche * not yet finished. 9301a547cbcSBart Van Assche * @is_sys_suspended: UFS device has been suspended because of system suspend 931afdfff59SYaniv Gardi * @urgent_bkops_lvl: keeps track of urgent bkops level for device 932afdfff59SYaniv Gardi * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for 933afdfff59SYaniv Gardi * device is known or not. 934ba810437SJohan Hovold * @wb_mutex: used to serialize devfreq and sysfs write booster toggling 935cff91dafSBart Van Assche * @clk_scaling_lock: used to serialize device commands and clock scaling 936cff91dafSBart Van Assche * @desc_size: descriptor sizes reported by device 937cff91dafSBart Van Assche * @bsg_dev: struct device associated with the BSG queue 938cff91dafSBart Van Assche * @bsg_queue: BSG queue associated with the UFS controller 939cff91dafSBart Van Assche * @rpm_dev_flush_recheck_work: used to suspend from RPM (runtime power 940cff91dafSBart Van Assche * management) after the UFS device has finished a WriteBooster buffer 941cff91dafSBart Van Assche * flush or auto BKOP. 942cff91dafSBart Van Assche * @monitor: statistics about UFS commands 94370297a8aSSatya Tangirala * @crypto_capabilities: Content of crypto capabilities register (0x100) 94470297a8aSSatya Tangirala * @crypto_cap_array: Array of crypto capabilities 94570297a8aSSatya Tangirala * @crypto_cfg_register: Start of the crypto cfg array 946cb77cb5aSEric Biggers * @crypto_profile: the crypto profile of this hba (if applicable) 947cff91dafSBart Van Assche * @debugfs_root: UFS controller debugfs root directory 948cff91dafSBart Van Assche * @debugfs_ee_work: used to restore ee_ctrl_mask after a delay 949cff91dafSBart Van Assche * @debugfs_ee_rate_limit_ms: user configurable delay after which to restore 950cff91dafSBart Van Assche * ee_ctrl_mask 951cff91dafSBart Van Assche * @luns_avail: number of regular and well known LUNs supported by the UFS 952cff91dafSBart Van Assche * device 95357b1c0efSAsutosh Das * @nr_hw_queues: number of hardware queues configured 95457b1c0efSAsutosh Das * @nr_queues: number of Queues of different queue types 955cff91dafSBart Van Assche * @complete_put: whether or not to call ufshcd_rpm_put() from inside 956cff91dafSBart Van Assche * ufshcd_resume_complete() 957305a357dSAsutosh Das * @mcq_sup: is mcq supported by UFSHC 9582468da61SAsutosh Das * @mcq_enabled: is mcq ready to accept requests 959c263b4efSAsutosh Das * @res: array of resource info of MCQ registers 960c263b4efSAsutosh Das * @mcq_base: Multi circular queue registers base address 9614682abfaSAsutosh Das * @uhq: array of supported hardware queues 9624682abfaSAsutosh Das * @dev_cmd_queue: Queue for issuing device management commands 9636bf999e0SBean Huo * @mcq_opr: MCQ operation and runtime registers 9646bf999e0SBean Huo * @ufs_rtc_update_work: A work for UFS RTC periodic update 9652777e73fSMaramaina Naresh * @pm_qos_req: PM QoS request handle 9662777e73fSMaramaina Naresh * @pm_qos_enabled: flag to check if pm qos is enabled 967e0eca63eSVinayak Holikatti */ 968e0eca63eSVinayak Holikatti struct ufs_hba { 969e0eca63eSVinayak Holikatti void __iomem *mmio_base; 970e0eca63eSVinayak Holikatti 971e0eca63eSVinayak Holikatti /* Virtual memory reference */ 972e0eca63eSVinayak Holikatti struct utp_transfer_cmd_desc *ucdl_base_addr; 973e0eca63eSVinayak Holikatti struct utp_transfer_req_desc *utrdl_base_addr; 974e0eca63eSVinayak Holikatti struct utp_task_req_desc *utmrdl_base_addr; 975e0eca63eSVinayak Holikatti 976e0eca63eSVinayak Holikatti /* DMA memory reference */ 977e0eca63eSVinayak Holikatti dma_addr_t ucdl_dma_addr; 978e0eca63eSVinayak Holikatti dma_addr_t utrdl_dma_addr; 979e0eca63eSVinayak Holikatti dma_addr_t utmrdl_dma_addr; 980e0eca63eSVinayak Holikatti 981e0eca63eSVinayak Holikatti struct Scsi_Host *host; 982e0eca63eSVinayak Holikatti struct device *dev; 983e2106584SBart Van Assche struct scsi_device *ufs_device_wlun; 984e0eca63eSVinayak Holikatti 985e88e2d32SAvri Altman #ifdef CONFIG_SCSI_UFS_HWMON 986e88e2d32SAvri Altman struct device *hwmon_device; 987e88e2d32SAvri Altman #endif 988e88e2d32SAvri Altman 98957d104c1SSubhash Jadavani enum ufs_dev_pwr_mode curr_dev_pwr_mode; 99057d104c1SSubhash Jadavani enum uic_link_state uic_link_state; 99157d104c1SSubhash Jadavani /* Desired UFS power management level during runtime PM */ 99257d104c1SSubhash Jadavani enum ufs_pm_level rpm_lvl; 99357d104c1SSubhash Jadavani /* Desired UFS power management level during system PM */ 99457d104c1SSubhash Jadavani enum ufs_pm_level spm_lvl; 99557d104c1SSubhash Jadavani int pm_op_in_progress; 99657d104c1SSubhash Jadavani 997ad448378SAdrian Hunter /* Auto-Hibernate Idle Timer register value */ 998ad448378SAdrian Hunter u32 ahit; 999ad448378SAdrian Hunter 1000e0eca63eSVinayak Holikatti struct ufshcd_lrb *lrb; 1001e0eca63eSVinayak Holikatti 1002e0eca63eSVinayak Holikatti unsigned long outstanding_tasks; 1003169f5eb2SBart Van Assche spinlock_t outstanding_lock; 1004e0eca63eSVinayak Holikatti unsigned long outstanding_reqs; 1005e0eca63eSVinayak Holikatti 1006e0eca63eSVinayak Holikatti u32 capabilities; 1007e0eca63eSVinayak Holikatti int nutrs; 10089ec54934SAvri Altman int nortt; 10096e1d850aSAsutosh Das u32 mcq_capabilities; 1010e0eca63eSVinayak Holikatti int nutmrs; 1011945c3ccaSBart Van Assche u32 reserved_slot; 1012e0eca63eSVinayak Holikatti u32 ufs_version; 1013176eb927SArnd Bergmann const struct ufs_hba_variant_ops *vops; 101490b8491cSStanley Chu struct ufs_hba_variant_params *vps; 10155c0c28a8SSujit Reddy Thumma void *priv; 1016ada1e653SEric Biggers #ifdef CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE 1017ada1e653SEric Biggers size_t sg_entry_size; 1018ada1e653SEric Biggers #endif 1019e0eca63eSVinayak Holikatti unsigned int irq; 102057d104c1SSubhash Jadavani bool is_irq_enabled; 10219e1e8a75SSubhash Jadavani enum ufs_ref_clk_freq dev_ref_clk_freq; 1022e0eca63eSVinayak Holikatti 1023cad2e03dSYaniv Gardi unsigned int quirks; /* Deviations from standard UFSHCI spec. */ 10246ccf44feSSeungwon Jeon 1025c58ab7aaSYaniv Gardi /* Device deviations from standard UFS device spec. */ 1026c58ab7aaSYaniv Gardi unsigned int dev_quirks; 1027c58ab7aaSYaniv Gardi 102869a6c269SBart Van Assche struct blk_mq_tag_set tmf_tag_set; 102969a6c269SBart Van Assche struct request_queue *tmf_queue; 1030f5ef336fSAdrian Hunter struct request **tmf_rqs; 1031e0eca63eSVinayak Holikatti 103257d104c1SSubhash Jadavani struct uic_command *active_uic_cmd; 103357d104c1SSubhash Jadavani struct mutex uic_cmd_mutex; 103457d104c1SSubhash Jadavani struct completion *uic_async_done; 103553b3d9c3SSeungwon Jeon 10369c202090SBart Van Assche enum ufshcd_state ufshcd_state; 10373441da7dSSujit Reddy Thumma u32 eh_flags; 10382fbd009bSSeungwon Jeon u32 intr_mask; 1039cff91dafSBart Van Assche u16 ee_ctrl_mask; 1040cff91dafSBart Van Assche u16 ee_drv_mask; 1041cff91dafSBart Van Assche u16 ee_usr_mask; 1042cd469475SAdrian Hunter struct mutex ee_ctrl_mutex; 10431d337ec2SSujit Reddy Thumma bool is_powered; 10449cd20d3fSCan Guo bool shutting_down; 10459cd20d3fSCan Guo struct semaphore host_sem; 1046e0eca63eSVinayak Holikatti 1047e0eca63eSVinayak Holikatti /* Work Queues */ 104888b09900SAdrian Hunter struct workqueue_struct *eh_wq; 104988b09900SAdrian Hunter struct work_struct eh_work; 105066ec6d59SSujit Reddy Thumma struct work_struct eeh_work; 1051e0eca63eSVinayak Holikatti 1052e0eca63eSVinayak Holikatti /* HBA Errors */ 1053e0eca63eSVinayak Holikatti u32 errors; 1054e8e7f271SSujit Reddy Thumma u32 uic_error; 1055e8e7f271SSujit Reddy Thumma u32 saved_err; 1056e8e7f271SSujit Reddy Thumma u32 saved_uic_err; 1057ff8e20c6SDolev Raviv struct ufs_stats ufs_stats; 10584db7a236SCan Guo bool force_reset; 10592355b66eSCan Guo bool force_pmc; 10602df74b69SCan Guo bool silence_err_logs; 10615a0b0cb9SSujit Reddy Thumma 10625a0b0cb9SSujit Reddy Thumma /* Device management request data */ 10635a0b0cb9SSujit Reddy Thumma struct ufs_dev_cmd dev_cmd; 1064cad2e03dSYaniv Gardi ktime_t last_dme_cmd_tstamp; 10651cbc9ad3SAdrian Hunter int nop_out_timeout; 106666ec6d59SSujit Reddy Thumma 106757d104c1SSubhash Jadavani /* Keeps information of the UFS device connected to this host */ 106857d104c1SSubhash Jadavani struct ufs_dev_info dev_info; 106966ec6d59SSujit Reddy Thumma bool auto_bkops_enabled; 1070aa497613SSujit Reddy Thumma struct ufs_vreg_info vreg_info; 1071c6e79dacSSujit Reddy Thumma struct list_head clk_list_head; 1072930bd77eSManivannan Sadhasivam bool use_pm_opp; 107357d104c1SSubhash Jadavani 10747fabb77bSGilad Broner /* Number of requests aborts */ 10757fabb77bSGilad Broner int req_abort_count; 10767fabb77bSGilad Broner 107754b879b7SYaniv Gardi /* Number of lanes available (1 or 2) for Rx/Tx */ 107854b879b7SYaniv Gardi u32 lanes_per_direction; 10797eb584dbSDolev Raviv struct ufs_pa_layer_attr pwr_info; 10807eb584dbSDolev Raviv struct ufs_pwr_mode_info max_pwr_info; 10811ab27c9cSSahitya Tummala 10821ab27c9cSSahitya Tummala struct ufs_clk_gating clk_gating; 10831ab27c9cSSahitya Tummala /* Control to enable/disable host capabilities */ 10841ab27c9cSSahitya Tummala u32 caps; 1085856b3483SSahitya Tummala 1086856b3483SSahitya Tummala struct devfreq *devfreq; 1087856b3483SSahitya Tummala struct ufs_clk_scaling clk_scaling; 10881a547cbcSBart Van Assche bool system_suspending; 1089e785060eSDolev Raviv bool is_sys_suspended; 1090afdfff59SYaniv Gardi 1091afdfff59SYaniv Gardi enum bkops_status urgent_bkops_lvl; 1092afdfff59SYaniv Gardi bool is_urgent_bkops_lvl_checked; 1093a3cd5ec5Ssubhashj@codeaurora.org 1094ba810437SJohan Hovold struct mutex wb_mutex; 1095a3cd5ec5Ssubhashj@codeaurora.org struct rw_semaphore clk_scaling_lock; 1096df032bf2SAvri Altman 1097df032bf2SAvri Altman struct device bsg_dev; 1098df032bf2SAvri Altman struct request_queue *bsg_queue; 109951dd905bSStanley Chu struct delayed_work rpm_dev_flush_recheck_work; 110070297a8aSSatya Tangirala 11011d8613a2SCan Guo struct ufs_hba_monitor monitor; 11021d8613a2SCan Guo 110370297a8aSSatya Tangirala #ifdef CONFIG_SCSI_UFS_CRYPTO 110470297a8aSSatya Tangirala union ufs_crypto_capabilities crypto_capabilities; 110570297a8aSSatya Tangirala union ufs_crypto_cap_entry *crypto_cap_array; 110670297a8aSSatya Tangirala u32 crypto_cfg_register; 1107cb77cb5aSEric Biggers struct blk_crypto_profile crypto_profile; 110870297a8aSSatya Tangirala #endif 1109b6cacaf2SAdrian Hunter #ifdef CONFIG_DEBUG_FS 1110b6cacaf2SAdrian Hunter struct dentry *debugfs_root; 11117deedfdaSAdrian Hunter struct delayed_work debugfs_ee_work; 11127deedfdaSAdrian Hunter u32 debugfs_ee_rate_limit_ms; 1113b6cacaf2SAdrian Hunter #endif 1114045da307SAkinobu Mita #ifdef CONFIG_SCSI_UFS_FAULT_INJECTION 1115045da307SAkinobu Mita struct fault_attr trigger_eh_attr; 1116045da307SAkinobu Mita struct fault_attr timeout_attr; 1117045da307SAkinobu Mita #endif 1118b294ff3eSAsutosh Das u32 luns_avail; 111957b1c0efSAsutosh Das unsigned int nr_hw_queues; 112057b1c0efSAsutosh Das unsigned int nr_queues[HCTX_MAX_TYPES]; 1121b294ff3eSAsutosh Das bool complete_put; 11220cab4023SAsutosh Das bool scsi_host_added; 1123305a357dSAsutosh Das bool mcq_sup; 11240c60eb0cSKyoungrul Kim bool lsdb_sup; 11252468da61SAsutosh Das bool mcq_enabled; 1126c263b4efSAsutosh Das struct ufshcd_res_info res[RES_MAX]; 1127c263b4efSAsutosh Das void __iomem *mcq_base; 11284682abfaSAsutosh Das struct ufs_hw_queue *uhq; 11294682abfaSAsutosh Das struct ufs_hw_queue *dev_cmd_queue; 11302468da61SAsutosh Das struct ufshcd_mcq_opr_info_t mcq_opr[OPR_MAX]; 11316bf999e0SBean Huo 11326bf999e0SBean Huo struct delayed_work ufs_rtc_update_work; 11332777e73fSMaramaina Naresh struct pm_qos_request pm_qos_req; 11342777e73fSMaramaina Naresh bool pm_qos_enabled; 1135e0eca63eSVinayak Holikatti }; 1136e0eca63eSVinayak Holikatti 11374682abfaSAsutosh Das /** 11384682abfaSAsutosh Das * struct ufs_hw_queue - per hardware queue structure 11392468da61SAsutosh Das * @mcq_sq_head: base address of submission queue head pointer 11402468da61SAsutosh Das * @mcq_sq_tail: base address of submission queue tail pointer 11412468da61SAsutosh Das * @mcq_cq_head: base address of completion queue head pointer 11422468da61SAsutosh Das * @mcq_cq_tail: base address of completion queue tail pointer 11434682abfaSAsutosh Das * @sqe_base_addr: submission queue entry base address 11444682abfaSAsutosh Das * @sqe_dma_addr: submission queue dma address 11454682abfaSAsutosh Das * @cqe_base_addr: completion queue base address 11464682abfaSAsutosh Das * @cqe_dma_addr: completion queue dma address 11474682abfaSAsutosh Das * @max_entries: max number of slots in this hardware queue 11482468da61SAsutosh Das * @id: hardware queue ID 114922a2d563SAsutosh Das * @sq_tp_slot: current slot to which SQ tail pointer is pointing 115022a2d563SAsutosh Das * @sq_lock: serialize submission queue access 1151f87b2c41SAsutosh Das * @cq_tail_slot: current slot to which CQ tail pointer is pointing 1152f87b2c41SAsutosh Das * @cq_head_slot: current slot to which CQ head pointer is pointing 1153ed975065SAsutosh Das * @cq_lock: Synchronize between multiple polling instances 11548d729034SBao D. Nguyen * @sq_mutex: prevent submission queue concurrent access 11554682abfaSAsutosh Das */ 11564682abfaSAsutosh Das struct ufs_hw_queue { 11572468da61SAsutosh Das void __iomem *mcq_sq_head; 11582468da61SAsutosh Das void __iomem *mcq_sq_tail; 11592468da61SAsutosh Das void __iomem *mcq_cq_head; 11602468da61SAsutosh Das void __iomem *mcq_cq_tail; 11612468da61SAsutosh Das 11623c85f087SAvri Altman struct utp_transfer_req_desc *sqe_base_addr; 11634682abfaSAsutosh Das dma_addr_t sqe_dma_addr; 11644682abfaSAsutosh Das struct cq_entry *cqe_base_addr; 11654682abfaSAsutosh Das dma_addr_t cqe_dma_addr; 11664682abfaSAsutosh Das u32 max_entries; 11672468da61SAsutosh Das u32 id; 116822a2d563SAsutosh Das u32 sq_tail_slot; 116922a2d563SAsutosh Das spinlock_t sq_lock; 1170f87b2c41SAsutosh Das u32 cq_tail_slot; 1171f87b2c41SAsutosh Das u32 cq_head_slot; 1172ed975065SAsutosh Das spinlock_t cq_lock; 11738d729034SBao D. Nguyen /* prevent concurrent access to submission queue */ 11748d729034SBao D. Nguyen struct mutex sq_mutex; 1175e0eca63eSVinayak Holikatti }; 1176e0eca63eSVinayak Holikatti 1177e8a1d87bSMinwoo Im #define MCQ_QCFG_SIZE 0x40 1178e8a1d87bSMinwoo Im 11792fc39848SMinwoo Im static inline unsigned int ufshcd_mcq_opr_offset(struct ufs_hba *hba, 11802fc39848SMinwoo Im enum ufshcd_mcq_opr opr, int idx) 11812fc39848SMinwoo Im { 11822fc39848SMinwoo Im return hba->mcq_opr[opr].offset + hba->mcq_opr[opr].stride * idx; 11832fc39848SMinwoo Im } 11842fc39848SMinwoo Im 1185e8a1d87bSMinwoo Im static inline unsigned int ufshcd_mcq_cfg_offset(unsigned int reg, int idx) 1186e8a1d87bSMinwoo Im { 1187e8a1d87bSMinwoo Im return reg + MCQ_QCFG_SIZE * idx; 1188e8a1d87bSMinwoo Im } 1189e8a1d87bSMinwoo Im 1190ada1e653SEric Biggers #ifdef CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE 1191ada1e653SEric Biggers static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba) 1192ada1e653SEric Biggers { 1193ada1e653SEric Biggers return hba->sg_entry_size; 1194ada1e653SEric Biggers } 1195ada1e653SEric Biggers 1196ada1e653SEric Biggers static inline void ufshcd_set_sg_entry_size(struct ufs_hba *hba, size_t sg_entry_size) 1197ada1e653SEric Biggers { 1198ada1e653SEric Biggers WARN_ON_ONCE(sg_entry_size < sizeof(struct ufshcd_sg_entry)); 1199ada1e653SEric Biggers hba->sg_entry_size = sg_entry_size; 1200ada1e653SEric Biggers } 1201ada1e653SEric Biggers #else 1202ada1e653SEric Biggers static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba) 1203ada1e653SEric Biggers { 1204ada1e653SEric Biggers return sizeof(struct ufshcd_sg_entry); 1205ada1e653SEric Biggers } 1206ada1e653SEric Biggers 1207ada1e653SEric Biggers #define ufshcd_set_sg_entry_size(hba, sg_entry_size) \ 1208ada1e653SEric Biggers ({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); }) 1209ada1e653SEric Biggers #endif 1210ada1e653SEric Biggers 121175d0c649SEric Biggers #ifdef CONFIG_SCSI_UFS_CRYPTO 121275d0c649SEric Biggers static inline struct ufs_hba * 121375d0c649SEric Biggers ufs_hba_from_crypto_profile(struct blk_crypto_profile *profile) 121475d0c649SEric Biggers { 121575d0c649SEric Biggers return container_of(profile, struct ufs_hba, crypto_profile); 121675d0c649SEric Biggers } 121775d0c649SEric Biggers #endif 121875d0c649SEric Biggers 121906caeb53SPo-Wen Kao static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba) 1220ada1e653SEric Biggers { 1221ada1e653SEric Biggers return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba); 1222ada1e653SEric Biggers } 1223ada1e653SEric Biggers 12241ab27c9cSSahitya Tummala /* Returns true if clocks can be gated. Otherwise false */ 12251ab27c9cSSahitya Tummala static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) 12261ab27c9cSSahitya Tummala { 12271ab27c9cSSahitya Tummala return hba->caps & UFSHCD_CAP_CLK_GATING; 12281ab27c9cSSahitya Tummala } 12291ab27c9cSSahitya Tummala static inline bool ufshcd_can_hibern8_during_gating(struct ufs_hba *hba) 12301ab27c9cSSahitya Tummala { 12311ab27c9cSSahitya Tummala return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; 12321ab27c9cSSahitya Tummala } 1233fcb0c4b0SSahitya Tummala static inline int ufshcd_is_clkscaling_supported(struct ufs_hba *hba) 1234856b3483SSahitya Tummala { 1235856b3483SSahitya Tummala return hba->caps & UFSHCD_CAP_CLK_SCALING; 1236856b3483SSahitya Tummala } 1237374a246eSSubhash Jadavani static inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba) 1238374a246eSSubhash Jadavani { 1239374a246eSSubhash Jadavani return hba->caps & UFSHCD_CAP_AUTO_BKOPS_SUSPEND; 1240374a246eSSubhash Jadavani } 124149615ba1SStanley Chu static inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba) 124249615ba1SStanley Chu { 124349615ba1SStanley Chu return hba->caps & UFSHCD_CAP_RPM_AUTOSUSPEND; 124449615ba1SStanley Chu } 1245374a246eSSubhash Jadavani 1246b852190eSYaniv Gardi static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba) 1247b852190eSYaniv Gardi { 12481c0810e7SKeoseong Park return (hba->caps & UFSHCD_CAP_INTR_AGGR) && 12491c0810e7SKeoseong Park !(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR); 1250b852190eSYaniv Gardi } 1251b852190eSYaniv Gardi 1252dd7143e2SCan Guo static inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba) 1253dd7143e2SCan Guo { 1254dd7143e2SCan Guo return !!(ufshcd_is_link_hibern8(hba) && 1255dd7143e2SCan Guo (hba->caps & UFSHCD_CAP_AGGR_POWER_COLLAPSE)); 1256dd7143e2SCan Guo } 1257dd7143e2SCan Guo 1258ee5f1042SStanley Chu static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) 1259ee5f1042SStanley Chu { 12608da76f71SAdrian Hunter return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) && 12618da76f71SAdrian Hunter !(hba->quirks & UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8); 1262ee5f1042SStanley Chu } 1263ee5f1042SStanley Chu 12645a244e0eSStanley Chu static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) 12655a244e0eSStanley Chu { 126651d1628fSBart Van Assche return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit); 12675a244e0eSStanley Chu } 12685a244e0eSStanley Chu 12693d17b9b5SAsutosh Das static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba) 12703d17b9b5SAsutosh Das { 12713d17b9b5SAsutosh Das return hba->caps & UFSHCD_CAP_WB_EN; 12723d17b9b5SAsutosh Das } 12733d17b9b5SAsutosh Das 127487bd0501SPeter Wang static inline bool ufshcd_enable_wb_if_scaling_up(struct ufs_hba *hba) 127587bd0501SPeter Wang { 127687bd0501SPeter Wang return hba->caps & UFSHCD_CAP_WB_WITH_CLK_SCALING; 127787bd0501SPeter Wang } 127887bd0501SPeter Wang 12792468da61SAsutosh Das #define ufsmcq_writel(hba, val, reg) \ 12802468da61SAsutosh Das writel((val), (hba)->mcq_base + (reg)) 12812468da61SAsutosh Das #define ufsmcq_readl(hba, reg) \ 12822468da61SAsutosh Das readl((hba)->mcq_base + (reg)) 12832468da61SAsutosh Das 12842468da61SAsutosh Das #define ufsmcq_writelx(hba, val, reg) \ 12852468da61SAsutosh Das writel_relaxed((val), (hba)->mcq_base + (reg)) 12862468da61SAsutosh Das #define ufsmcq_readlx(hba, reg) \ 12872468da61SAsutosh Das readl_relaxed((hba)->mcq_base + (reg)) 12882468da61SAsutosh Das 1289b873a275SSeungwon Jeon #define ufshcd_writel(hba, val, reg) \ 1290b873a275SSeungwon Jeon writel((val), (hba)->mmio_base + (reg)) 1291b873a275SSeungwon Jeon #define ufshcd_readl(hba, reg) \ 1292b873a275SSeungwon Jeon readl((hba)->mmio_base + (reg)) 1293b873a275SSeungwon Jeon 1294e785060eSDolev Raviv /** 1295cff91dafSBart Van Assche * ufshcd_rmwl - perform read/modify/write for a controller register 1296cff91dafSBart Van Assche * @hba: per adapter instance 1297cff91dafSBart Van Assche * @mask: mask to apply on read value 1298cff91dafSBart Van Assche * @val: actual value to write 1299cff91dafSBart Van Assche * @reg: register address 1300e785060eSDolev Raviv */ 1301e785060eSDolev Raviv static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg) 1302e785060eSDolev Raviv { 1303e785060eSDolev Raviv u32 tmp; 1304e785060eSDolev Raviv 1305e785060eSDolev Raviv tmp = ufshcd_readl(hba, reg); 1306e785060eSDolev Raviv tmp &= ~mask; 1307e785060eSDolev Raviv tmp |= (val & mask); 1308e785060eSDolev Raviv ufshcd_writel(hba, tmp, reg); 1309e785060eSDolev Raviv } 1310e785060eSDolev Raviv 13110ae7a027SManivannan Sadhasivam void ufshcd_enable_irq(struct ufs_hba *hba); 13120ae7a027SManivannan Sadhasivam void ufshcd_disable_irq(struct ufs_hba *hba); 13135c0c28a8SSujit Reddy Thumma int ufshcd_alloc_host(struct device *, struct ufs_hba **); 131447555a5cSYaniv Gardi void ufshcd_dealloc_host(struct ufs_hba *); 13159d19bf7aSStanley Chu int ufshcd_hba_enable(struct ufs_hba *hba); 13165c0c28a8SSujit Reddy Thumma int ufshcd_init(struct ufs_hba *, void __iomem *, unsigned int); 1317087c5efaSStanley Chu int ufshcd_link_recovery(struct ufs_hba *hba); 13189d19bf7aSStanley Chu int ufshcd_make_hba_operational(struct ufs_hba *hba); 1319e0eca63eSVinayak Holikatti void ufshcd_remove(struct ufs_hba *); 1320525943a5SAsutosh Das int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); 13219d19bf7aSStanley Chu int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); 13225c955c10SStanley Chu void ufshcd_delay_us(unsigned long us, unsigned long tolerance); 13239e1e8a75SSubhash Jadavani void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk); 1324e965e5e0SStanley Chu void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val); 13253a95f5b3SAlice.Chao void ufshcd_hba_stop(struct ufs_hba *hba); 1326267a59f6SBart Van Assche void ufshcd_schedule_eh_work(struct ufs_hba *hba); 132711afb65cSPo-Wen Kao void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds); 1328175d1825SMinwoo Im unsigned int ufshcd_mcq_queue_cfg_addr(struct ufs_hba *hba); 132911afb65cSPo-Wen Kao u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i); 1330e02288e0SCan Guo void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i); 133157d6ef46SBao D. Nguyen unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba, 1332e02288e0SCan Guo struct ufs_hw_queue *hwq); 133311afb65cSPo-Wen Kao void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba); 1334ab3e6c4eSChanWoo Lee void ufshcd_mcq_enable(struct ufs_hba *hba); 1335a085e037SBart Van Assche void ufshcd_mcq_enable_esi(struct ufs_hba *hba); 1336e02288e0SCan Guo void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg); 1337e0eca63eSVinayak Holikatti 133872208ebeSManivannan Sadhasivam int ufshcd_opp_config_clks(struct device *dev, struct opp_table *opp_table, 133972208ebeSManivannan Sadhasivam struct dev_pm_opp *opp, void *data, 134072208ebeSManivannan Sadhasivam bool scaling_down); 13411ce5898aSYaniv Gardi /** 13421ce5898aSYaniv Gardi * ufshcd_set_variant - set variant specific data to the hba 1343cff91dafSBart Van Assche * @hba: per adapter instance 1344cff91dafSBart Van Assche * @variant: pointer to variant specific data 13451ce5898aSYaniv Gardi */ 13461ce5898aSYaniv Gardi static inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant) 13471ce5898aSYaniv Gardi { 13481ce5898aSYaniv Gardi BUG_ON(!hba); 13491ce5898aSYaniv Gardi hba->priv = variant; 13501ce5898aSYaniv Gardi } 13511ce5898aSYaniv Gardi 13521ce5898aSYaniv Gardi /** 13531ce5898aSYaniv Gardi * ufshcd_get_variant - get variant specific data from the hba 1354cff91dafSBart Van Assche * @hba: per adapter instance 13551ce5898aSYaniv Gardi */ 13561ce5898aSYaniv Gardi static inline void *ufshcd_get_variant(struct ufs_hba *hba) 13571ce5898aSYaniv Gardi { 13581ce5898aSYaniv Gardi BUG_ON(!hba); 13591ce5898aSYaniv Gardi return hba->priv; 13601ce5898aSYaniv Gardi } 1361e88e2d32SAvri Altman 13629bb25e5dSBart Van Assche #ifdef CONFIG_PM 1363f1ecbe1eSBart Van Assche extern int ufshcd_runtime_suspend(struct device *dev); 1364f1ecbe1eSBart Van Assche extern int ufshcd_runtime_resume(struct device *dev); 13659bb25e5dSBart Van Assche #endif 13669bb25e5dSBart Van Assche #ifdef CONFIG_PM_SLEEP 1367f1ecbe1eSBart Van Assche extern int ufshcd_system_suspend(struct device *dev); 1368f1ecbe1eSBart Van Assche extern int ufshcd_system_resume(struct device *dev); 136988441a8dSAnjana Hari extern int ufshcd_system_freeze(struct device *dev); 137088441a8dSAnjana Hari extern int ufshcd_system_thaw(struct device *dev); 137188441a8dSAnjana Hari extern int ufshcd_system_restore(struct device *dev); 13729bb25e5dSBart Van Assche #endif 137388441a8dSAnjana Hari 1374fc85a74eSStanley Chu extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba, 1375fc85a74eSStanley Chu int agreed_gear, 1376fc85a74eSStanley Chu int adapt_val); 137712b4fdb4SSeungwon Jeon extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, 137812b4fdb4SSeungwon Jeon u8 attr_set, u32 mib_val, u8 peer); 137912b4fdb4SSeungwon Jeon extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, 138012b4fdb4SSeungwon Jeon u32 *mib_val, u8 peer); 13810d846e70SAlim Akhtar extern int ufshcd_config_pwr_mode(struct ufs_hba *hba, 13820d846e70SAlim Akhtar struct ufs_pa_layer_attr *desired_pwr_mode); 1383fc53683bSStanley Chu extern int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode); 138412b4fdb4SSeungwon Jeon 138512b4fdb4SSeungwon Jeon /* UIC command interfaces for DME primitives */ 138612b4fdb4SSeungwon Jeon #define DME_LOCAL 0 138712b4fdb4SSeungwon Jeon #define DME_PEER 1 138812b4fdb4SSeungwon Jeon #define ATTR_SET_NOR 0 /* NORMAL */ 138912b4fdb4SSeungwon Jeon #define ATTR_SET_ST 1 /* STATIC */ 139012b4fdb4SSeungwon Jeon 139112b4fdb4SSeungwon Jeon static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel, 139212b4fdb4SSeungwon Jeon u32 mib_val) 139312b4fdb4SSeungwon Jeon { 139412b4fdb4SSeungwon Jeon return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR, 139512b4fdb4SSeungwon Jeon mib_val, DME_LOCAL); 139612b4fdb4SSeungwon Jeon } 139712b4fdb4SSeungwon Jeon 139812b4fdb4SSeungwon Jeon static inline int ufshcd_dme_st_set(struct ufs_hba *hba, u32 attr_sel, 139912b4fdb4SSeungwon Jeon u32 mib_val) 140012b4fdb4SSeungwon Jeon { 140112b4fdb4SSeungwon Jeon return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST, 140212b4fdb4SSeungwon Jeon mib_val, DME_LOCAL); 140312b4fdb4SSeungwon Jeon } 140412b4fdb4SSeungwon Jeon 140512b4fdb4SSeungwon Jeon static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel, 140612b4fdb4SSeungwon Jeon u32 mib_val) 140712b4fdb4SSeungwon Jeon { 140812b4fdb4SSeungwon Jeon return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR, 140912b4fdb4SSeungwon Jeon mib_val, DME_PEER); 141012b4fdb4SSeungwon Jeon } 141112b4fdb4SSeungwon Jeon 141212b4fdb4SSeungwon Jeon static inline int ufshcd_dme_peer_st_set(struct ufs_hba *hba, u32 attr_sel, 141312b4fdb4SSeungwon Jeon u32 mib_val) 141412b4fdb4SSeungwon Jeon { 141512b4fdb4SSeungwon Jeon return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST, 141612b4fdb4SSeungwon Jeon mib_val, DME_PEER); 141712b4fdb4SSeungwon Jeon } 141812b4fdb4SSeungwon Jeon 141912b4fdb4SSeungwon Jeon static inline int ufshcd_dme_get(struct ufs_hba *hba, 142012b4fdb4SSeungwon Jeon u32 attr_sel, u32 *mib_val) 142112b4fdb4SSeungwon Jeon { 142212b4fdb4SSeungwon Jeon return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL); 142312b4fdb4SSeungwon Jeon } 142412b4fdb4SSeungwon Jeon 142512b4fdb4SSeungwon Jeon static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, 142612b4fdb4SSeungwon Jeon u32 attr_sel, u32 *mib_val) 142712b4fdb4SSeungwon Jeon { 142812b4fdb4SSeungwon Jeon return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER); 142912b4fdb4SSeungwon Jeon } 143012b4fdb4SSeungwon Jeon 1431f37aabcfSYaniv Gardi static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) 1432f37aabcfSYaniv Gardi { 1433f37aabcfSYaniv Gardi return (pwr_info->pwr_rx == FAST_MODE || 1434f37aabcfSYaniv Gardi pwr_info->pwr_rx == FASTAUTO_MODE) && 1435f37aabcfSYaniv Gardi (pwr_info->pwr_tx == FAST_MODE || 1436f37aabcfSYaniv Gardi pwr_info->pwr_tx == FASTAUTO_MODE); 1437f37aabcfSYaniv Gardi } 1438f37aabcfSYaniv Gardi 1439984eaac1SStanley Chu static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba) 1440984eaac1SStanley Chu { 1441984eaac1SStanley Chu return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); 1442984eaac1SStanley Chu } 1443984eaac1SStanley Chu 1444ba7af5ecSStanley Chu void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit); 1445aead21f3SBart Van Assche void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, 1446aead21f3SBart Van Assche const struct ufs_dev_quirk *fixups); 14474b828fe1STomas Winkler #define SD_ASCII_STD true 14484b828fe1STomas Winkler #define SD_RAW false 14494b828fe1STomas Winkler int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, 14504b828fe1STomas Winkler u8 **buf, bool ascii); 14512238d31cSStanislav Nijnikov 1452078f4f4bSBart Van Assche void ufshcd_hold(struct ufs_hba *hba); 14531ab27c9cSSahitya Tummala void ufshcd_release(struct ufs_hba *hba); 1454a4b0e8a4SPotomski, MichalX 1455ad8a647eSBart Van Assche void ufshcd_clkgate_delay_set(struct device *dev, unsigned long value); 1456ad8a647eSBart Van Assche 14571d6f9decSStanley Chu int ufshcd_get_vreg(struct device *dev, struct ufs_vreg *vreg); 14581d6f9decSStanley Chu 1459e77044c5SAvri Altman int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd); 1460e77044c5SAvri Altman 14616ff265fcSBean Huo int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, 14626ff265fcSBean Huo struct utp_upiu_req *rsp_upiu, struct ufs_ehs *ehs_req, 14636ff265fcSBean Huo struct ufs_ehs *ehs_rsp, int sg_cnt, 14646ff265fcSBean Huo struct scatterlist *sg_list, enum dma_data_direction dir); 14653b5f3c0dSYue Hu int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable); 14666c4148ceSJinyoung Choi int ufshcd_wb_toggle_buf_flush(struct ufs_hba *hba, bool enable); 1467b294ff3eSAsutosh Das int ufshcd_suspend_prepare(struct device *dev); 1468ddba1cf7SAdrian Hunter int __ufshcd_suspend_prepare(struct device *dev, bool rpm_ok_for_spm); 1469b294ff3eSAsutosh Das void ufshcd_resume_complete(struct device *dev); 1470548fdf77SNitin Rawat bool ufshcd_is_hba_active(struct ufs_hba *hba); 14712777e73fSMaramaina Naresh void ufshcd_pm_qos_init(struct ufs_hba *hba); 14722777e73fSMaramaina Naresh void ufshcd_pm_qos_exit(struct ufs_hba *hba); 14738e834ca5SBean Huo 14740263bcd0SYaniv Gardi /* Wrapper functions for safely calling variant operations */ 14750263bcd0SYaniv Gardi static inline int ufshcd_vops_init(struct ufs_hba *hba) 14760263bcd0SYaniv Gardi { 14770263bcd0SYaniv Gardi if (hba->vops && hba->vops->init) 14780263bcd0SYaniv Gardi return hba->vops->init(hba); 14790263bcd0SYaniv Gardi 14800263bcd0SYaniv Gardi return 0; 14810263bcd0SYaniv Gardi } 14820263bcd0SYaniv Gardi 148392bcebe4SStanley Chu static inline int ufshcd_vops_phy_initialization(struct ufs_hba *hba) 148492bcebe4SStanley Chu { 148592bcebe4SStanley Chu if (hba->vops && hba->vops->phy_initialization) 148692bcebe4SStanley Chu return hba->vops->phy_initialization(hba); 148792bcebe4SStanley Chu 148892bcebe4SStanley Chu return 0; 148992bcebe4SStanley Chu } 149092bcebe4SStanley Chu 149135d11ec2SKrzysztof Kozlowski extern const struct ufs_pm_lvl_states ufs_pm_lvl_states[]; 1492cbb6813eSStanislav Nijnikov 1493ba80917dSTomas Winkler int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len, 1494ba80917dSTomas Winkler const char *prefix); 1495ba80917dSTomas Winkler 14967deedfdaSAdrian Hunter int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask); 14977deedfdaSAdrian Hunter int ufshcd_write_ee_control(struct ufs_hba *hba); 149835d11ec2SKrzysztof Kozlowski int ufshcd_update_ee_control(struct ufs_hba *hba, u16 *mask, 149935d11ec2SKrzysztof Kozlowski const u16 *other_mask, u16 set, u16 clr); 1500cd469475SAdrian Hunter 1501e0eca63eSVinayak Holikatti #endif /* End of Header */ 1502