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