mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
51dd905bd2
Currently UFS host driver promises VCC supply if UFS device needs to do WriteBooster flush during runtime suspend. However the UFS specification mentions: "While the flushing operation is in progress, the device is in Active power mode." Therefore UFS host driver needs to promise more: Keep UFS device as "Active power mode", otherwise UFS device shall not do any flush if device enters Sleep or PowerDown power mode. Similarly, the same promises shall be applied if device needs urgent BKOP during runtime suspend. Fix this by not changing device power mode if WriteBooster flush or urgent BKOP is required in ufshcd_suspend(). Now, if device finishes its job but is not resumed for a very long time, system will have unnecessary power drain because VCC is still supplied. A method to re-check the threshold of keeping VCC supply is required to fix the power drain. However, the threshold re-check needs to re-activate the link first because the decision depends on the latest device status. Also introduce a delayed work to force runtime resume after a certain delay during runtime suspend. This makes threshold re-check happen natually in the entry of the next runtime-suspend. The device can continue its WriteBooster flush or urgent BKOP jobs soon after resumed if device has no upcoming requests and link enters hibern8 state either by Auto-Hibern8 or hibern8 during clk-gating scheme. This solution not only prevents power drain but also makes as much use of time as possible for device's background jobs. Link: https://lore.kernel.org/r/20200522083212.4008-5-stanley.chu@mediatek.com Reviewed-by: Asutosh Das <asutoshd@codeaurora.org> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
599 lines
18 KiB
C
599 lines
18 KiB
C
/*
|
|
* Universal Flash Storage Host controller driver
|
|
*
|
|
* This code is based on drivers/scsi/ufs/ufs.h
|
|
* Copyright (C) 2011-2013 Samsung India Software Operations
|
|
*
|
|
* Authors:
|
|
* Santosh Yaraganavi <santosh.sy@samsung.com>
|
|
* Vinayak Holikatti <h.vinayak@samsung.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
* See the COPYING file in the top-level directory or visit
|
|
* <http://www.gnu.org/licenses/gpl-2.0.html>
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* This program is provided "AS IS" and "WITH ALL FAULTS" and
|
|
* without warranty of any kind. You are solely responsible for
|
|
* determining the appropriateness of using and distributing
|
|
* the program and assume all risks associated with your exercise
|
|
* of rights with respect to the program, including but not limited
|
|
* to infringement of third party rights, the risks and costs of
|
|
* program errors, damage to or loss of data, programs or equipment,
|
|
* and unavailability or interruption of operations. Under no
|
|
* circumstances will the contributor of this Program be liable for
|
|
* any damages of any kind arising from your use or distribution of
|
|
* this program.
|
|
*/
|
|
|
|
#ifndef _UFS_H
|
|
#define _UFS_H
|
|
|
|
#include <linux/mutex.h>
|
|
#include <linux/types.h>
|
|
#include <uapi/scsi/scsi_bsg_ufs.h>
|
|
|
|
#define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req))
|
|
#define QUERY_DESC_MAX_SIZE 255
|
|
#define QUERY_DESC_MIN_SIZE 2
|
|
#define QUERY_DESC_HDR_SIZE 2
|
|
#define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \
|
|
(sizeof(struct utp_upiu_header)))
|
|
#define UFS_SENSE_SIZE 18
|
|
|
|
#define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
|
|
cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
|
|
(byte1 << 8) | (byte0))
|
|
/*
|
|
* UFS device may have standard LUs and LUN id could be from 0x00 to
|
|
* 0x7F. Standard LUs use "Peripheral Device Addressing Format".
|
|
* UFS device may also have the Well Known LUs (also referred as W-LU)
|
|
* which again could be from 0x00 to 0x7F. For W-LUs, device only use
|
|
* the "Extended Addressing Format" which means the W-LUNs would be
|
|
* from 0xc100 (SCSI_W_LUN_BASE) onwards.
|
|
* This means max. LUN number reported from UFS device could be 0xC17F.
|
|
*/
|
|
#define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F
|
|
#define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
|
|
#define UFS_UPIU_WLUN_ID (1 << 7)
|
|
|
|
/* WriteBooster buffer is available only for the logical unit from 0 to 7 */
|
|
#define UFS_UPIU_MAX_WB_LUN_ID 8
|
|
|
|
/* Well known logical unit id in LUN field of UPIU */
|
|
enum {
|
|
UFS_UPIU_REPORT_LUNS_WLUN = 0x81,
|
|
UFS_UPIU_UFS_DEVICE_WLUN = 0xD0,
|
|
UFS_UPIU_BOOT_WLUN = 0xB0,
|
|
UFS_UPIU_RPMB_WLUN = 0xC4,
|
|
};
|
|
|
|
/*
|
|
* UFS Protocol Information Unit related definitions
|
|
*/
|
|
|
|
/* Task management functions */
|
|
enum {
|
|
UFS_ABORT_TASK = 0x01,
|
|
UFS_ABORT_TASK_SET = 0x02,
|
|
UFS_CLEAR_TASK_SET = 0x04,
|
|
UFS_LOGICAL_RESET = 0x08,
|
|
UFS_QUERY_TASK = 0x80,
|
|
UFS_QUERY_TASK_SET = 0x81,
|
|
};
|
|
|
|
/* UTP UPIU Transaction Codes Initiator to Target */
|
|
enum {
|
|
UPIU_TRANSACTION_NOP_OUT = 0x00,
|
|
UPIU_TRANSACTION_COMMAND = 0x01,
|
|
UPIU_TRANSACTION_DATA_OUT = 0x02,
|
|
UPIU_TRANSACTION_TASK_REQ = 0x04,
|
|
UPIU_TRANSACTION_QUERY_REQ = 0x16,
|
|
};
|
|
|
|
/* UTP UPIU Transaction Codes Target to Initiator */
|
|
enum {
|
|
UPIU_TRANSACTION_NOP_IN = 0x20,
|
|
UPIU_TRANSACTION_RESPONSE = 0x21,
|
|
UPIU_TRANSACTION_DATA_IN = 0x22,
|
|
UPIU_TRANSACTION_TASK_RSP = 0x24,
|
|
UPIU_TRANSACTION_READY_XFER = 0x31,
|
|
UPIU_TRANSACTION_QUERY_RSP = 0x36,
|
|
UPIU_TRANSACTION_REJECT_UPIU = 0x3F,
|
|
};
|
|
|
|
/* UPIU Read/Write flags */
|
|
enum {
|
|
UPIU_CMD_FLAGS_NONE = 0x00,
|
|
UPIU_CMD_FLAGS_WRITE = 0x20,
|
|
UPIU_CMD_FLAGS_READ = 0x40,
|
|
};
|
|
|
|
/* UPIU Task Attributes */
|
|
enum {
|
|
UPIU_TASK_ATTR_SIMPLE = 0x00,
|
|
UPIU_TASK_ATTR_ORDERED = 0x01,
|
|
UPIU_TASK_ATTR_HEADQ = 0x02,
|
|
UPIU_TASK_ATTR_ACA = 0x03,
|
|
};
|
|
|
|
/* UPIU Query request function */
|
|
enum {
|
|
UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01,
|
|
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
|
|
};
|
|
|
|
/* Flag idn for Query Requests*/
|
|
enum flag_idn {
|
|
QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
|
|
QUERY_FLAG_IDN_PERMANENT_WPE = 0x02,
|
|
QUERY_FLAG_IDN_PWR_ON_WPE = 0x03,
|
|
QUERY_FLAG_IDN_BKOPS_EN = 0x04,
|
|
QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE = 0x05,
|
|
QUERY_FLAG_IDN_PURGE_ENABLE = 0x06,
|
|
QUERY_FLAG_IDN_RESERVED2 = 0x07,
|
|
QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL = 0x08,
|
|
QUERY_FLAG_IDN_BUSY_RTC = 0x09,
|
|
QUERY_FLAG_IDN_RESERVED3 = 0x0A,
|
|
QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE = 0x0B,
|
|
QUERY_FLAG_IDN_WB_EN = 0x0E,
|
|
QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN = 0x0F,
|
|
QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8 = 0x10,
|
|
};
|
|
|
|
/* Attribute idn for Query requests */
|
|
enum attr_idn {
|
|
QUERY_ATTR_IDN_BOOT_LU_EN = 0x00,
|
|
QUERY_ATTR_IDN_RESERVED = 0x01,
|
|
QUERY_ATTR_IDN_POWER_MODE = 0x02,
|
|
QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
|
|
QUERY_ATTR_IDN_OOO_DATA_EN = 0x04,
|
|
QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
|
|
QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
|
|
QUERY_ATTR_IDN_MAX_DATA_IN = 0x07,
|
|
QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08,
|
|
QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09,
|
|
QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A,
|
|
QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B,
|
|
QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C,
|
|
QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
|
|
QUERY_ATTR_IDN_EE_STATUS = 0x0E,
|
|
QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F,
|
|
QUERY_ATTR_IDN_CNTX_CONF = 0x10,
|
|
QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11,
|
|
QUERY_ATTR_IDN_RESERVED2 = 0x12,
|
|
QUERY_ATTR_IDN_RESERVED3 = 0x13,
|
|
QUERY_ATTR_IDN_FFU_STATUS = 0x14,
|
|
QUERY_ATTR_IDN_PSA_STATE = 0x15,
|
|
QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16,
|
|
QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME = 0x17,
|
|
QUERY_ATTR_IDN_WB_FLUSH_STATUS = 0x1C,
|
|
QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE = 0x1D,
|
|
QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST = 0x1E,
|
|
QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE = 0x1F,
|
|
};
|
|
|
|
/* Descriptor idn for Query requests */
|
|
enum desc_idn {
|
|
QUERY_DESC_IDN_DEVICE = 0x0,
|
|
QUERY_DESC_IDN_CONFIGURATION = 0x1,
|
|
QUERY_DESC_IDN_UNIT = 0x2,
|
|
QUERY_DESC_IDN_RFU_0 = 0x3,
|
|
QUERY_DESC_IDN_INTERCONNECT = 0x4,
|
|
QUERY_DESC_IDN_STRING = 0x5,
|
|
QUERY_DESC_IDN_RFU_1 = 0x6,
|
|
QUERY_DESC_IDN_GEOMETRY = 0x7,
|
|
QUERY_DESC_IDN_POWER = 0x8,
|
|
QUERY_DESC_IDN_HEALTH = 0x9,
|
|
QUERY_DESC_IDN_MAX,
|
|
};
|
|
|
|
enum desc_header_offset {
|
|
QUERY_DESC_LENGTH_OFFSET = 0x00,
|
|
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
|
|
};
|
|
|
|
enum ufs_desc_def_size {
|
|
QUERY_DESC_DEVICE_DEF_SIZE = 0x59,
|
|
QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90,
|
|
QUERY_DESC_UNIT_DEF_SIZE = 0x2D,
|
|
QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06,
|
|
QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48,
|
|
QUERY_DESC_POWER_DEF_SIZE = 0x62,
|
|
QUERY_DESC_HEALTH_DEF_SIZE = 0x25,
|
|
};
|
|
|
|
/* Unit descriptor parameters offsets in bytes*/
|
|
enum unit_desc_param {
|
|
UNIT_DESC_PARAM_LEN = 0x0,
|
|
UNIT_DESC_PARAM_TYPE = 0x1,
|
|
UNIT_DESC_PARAM_UNIT_INDEX = 0x2,
|
|
UNIT_DESC_PARAM_LU_ENABLE = 0x3,
|
|
UNIT_DESC_PARAM_BOOT_LUN_ID = 0x4,
|
|
UNIT_DESC_PARAM_LU_WR_PROTECT = 0x5,
|
|
UNIT_DESC_PARAM_LU_Q_DEPTH = 0x6,
|
|
UNIT_DESC_PARAM_PSA_SENSITIVE = 0x7,
|
|
UNIT_DESC_PARAM_MEM_TYPE = 0x8,
|
|
UNIT_DESC_PARAM_DATA_RELIABILITY = 0x9,
|
|
UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA,
|
|
UNIT_DESC_PARAM_LOGICAL_BLK_COUNT = 0xB,
|
|
UNIT_DESC_PARAM_ERASE_BLK_SIZE = 0x13,
|
|
UNIT_DESC_PARAM_PROVISIONING_TYPE = 0x17,
|
|
UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18,
|
|
UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20,
|
|
UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22,
|
|
UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS = 0x29,
|
|
};
|
|
|
|
/* Device descriptor parameters offsets in bytes*/
|
|
enum device_desc_param {
|
|
DEVICE_DESC_PARAM_LEN = 0x0,
|
|
DEVICE_DESC_PARAM_TYPE = 0x1,
|
|
DEVICE_DESC_PARAM_DEVICE_TYPE = 0x2,
|
|
DEVICE_DESC_PARAM_DEVICE_CLASS = 0x3,
|
|
DEVICE_DESC_PARAM_DEVICE_SUB_CLASS = 0x4,
|
|
DEVICE_DESC_PARAM_PRTCL = 0x5,
|
|
DEVICE_DESC_PARAM_NUM_LU = 0x6,
|
|
DEVICE_DESC_PARAM_NUM_WLU = 0x7,
|
|
DEVICE_DESC_PARAM_BOOT_ENBL = 0x8,
|
|
DEVICE_DESC_PARAM_DESC_ACCSS_ENBL = 0x9,
|
|
DEVICE_DESC_PARAM_INIT_PWR_MODE = 0xA,
|
|
DEVICE_DESC_PARAM_HIGH_PR_LUN = 0xB,
|
|
DEVICE_DESC_PARAM_SEC_RMV_TYPE = 0xC,
|
|
DEVICE_DESC_PARAM_SEC_LU = 0xD,
|
|
DEVICE_DESC_PARAM_BKOP_TERM_LT = 0xE,
|
|
DEVICE_DESC_PARAM_ACTVE_ICC_LVL = 0xF,
|
|
DEVICE_DESC_PARAM_SPEC_VER = 0x10,
|
|
DEVICE_DESC_PARAM_MANF_DATE = 0x12,
|
|
DEVICE_DESC_PARAM_MANF_NAME = 0x14,
|
|
DEVICE_DESC_PARAM_PRDCT_NAME = 0x15,
|
|
DEVICE_DESC_PARAM_SN = 0x16,
|
|
DEVICE_DESC_PARAM_OEM_ID = 0x17,
|
|
DEVICE_DESC_PARAM_MANF_ID = 0x18,
|
|
DEVICE_DESC_PARAM_UD_OFFSET = 0x1A,
|
|
DEVICE_DESC_PARAM_UD_LEN = 0x1B,
|
|
DEVICE_DESC_PARAM_RTT_CAP = 0x1C,
|
|
DEVICE_DESC_PARAM_FRQ_RTC = 0x1D,
|
|
DEVICE_DESC_PARAM_UFS_FEAT = 0x1F,
|
|
DEVICE_DESC_PARAM_FFU_TMT = 0x20,
|
|
DEVICE_DESC_PARAM_Q_DPTH = 0x21,
|
|
DEVICE_DESC_PARAM_DEV_VER = 0x22,
|
|
DEVICE_DESC_PARAM_NUM_SEC_WPA = 0x24,
|
|
DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25,
|
|
DEVICE_DESC_PARAM_PSA_TMT = 0x29,
|
|
DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
|
|
DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP = 0x4F,
|
|
DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN = 0x53,
|
|
DEVICE_DESC_PARAM_WB_TYPE = 0x54,
|
|
DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS = 0x55,
|
|
};
|
|
|
|
/* Interconnect descriptor parameters offsets in bytes*/
|
|
enum interconnect_desc_param {
|
|
INTERCONNECT_DESC_PARAM_LEN = 0x0,
|
|
INTERCONNECT_DESC_PARAM_TYPE = 0x1,
|
|
INTERCONNECT_DESC_PARAM_UNIPRO_VER = 0x2,
|
|
INTERCONNECT_DESC_PARAM_MPHY_VER = 0x4,
|
|
};
|
|
|
|
/* Geometry descriptor parameters offsets in bytes*/
|
|
enum geometry_desc_param {
|
|
GEOMETRY_DESC_PARAM_LEN = 0x0,
|
|
GEOMETRY_DESC_PARAM_TYPE = 0x1,
|
|
GEOMETRY_DESC_PARAM_DEV_CAP = 0x4,
|
|
GEOMETRY_DESC_PARAM_MAX_NUM_LUN = 0xC,
|
|
GEOMETRY_DESC_PARAM_SEG_SIZE = 0xD,
|
|
GEOMETRY_DESC_PARAM_ALLOC_UNIT_SIZE = 0x11,
|
|
GEOMETRY_DESC_PARAM_MIN_BLK_SIZE = 0x12,
|
|
GEOMETRY_DESC_PARAM_OPT_RD_BLK_SIZE = 0x13,
|
|
GEOMETRY_DESC_PARAM_OPT_WR_BLK_SIZE = 0x14,
|
|
GEOMETRY_DESC_PARAM_MAX_IN_BUF_SIZE = 0x15,
|
|
GEOMETRY_DESC_PARAM_MAX_OUT_BUF_SIZE = 0x16,
|
|
GEOMETRY_DESC_PARAM_RPMB_RW_SIZE = 0x17,
|
|
GEOMETRY_DESC_PARAM_DYN_CAP_RSRC_PLC = 0x18,
|
|
GEOMETRY_DESC_PARAM_DATA_ORDER = 0x19,
|
|
GEOMETRY_DESC_PARAM_MAX_NUM_CTX = 0x1A,
|
|
GEOMETRY_DESC_PARAM_TAG_UNIT_SIZE = 0x1B,
|
|
GEOMETRY_DESC_PARAM_TAG_RSRC_SIZE = 0x1C,
|
|
GEOMETRY_DESC_PARAM_SEC_RM_TYPES = 0x1D,
|
|
GEOMETRY_DESC_PARAM_MEM_TYPES = 0x1E,
|
|
GEOMETRY_DESC_PARAM_SCM_MAX_NUM_UNITS = 0x20,
|
|
GEOMETRY_DESC_PARAM_SCM_CAP_ADJ_FCTR = 0x24,
|
|
GEOMETRY_DESC_PARAM_NPM_MAX_NUM_UNITS = 0x26,
|
|
GEOMETRY_DESC_PARAM_NPM_CAP_ADJ_FCTR = 0x2A,
|
|
GEOMETRY_DESC_PARAM_ENM1_MAX_NUM_UNITS = 0x2C,
|
|
GEOMETRY_DESC_PARAM_ENM1_CAP_ADJ_FCTR = 0x30,
|
|
GEOMETRY_DESC_PARAM_ENM2_MAX_NUM_UNITS = 0x32,
|
|
GEOMETRY_DESC_PARAM_ENM2_CAP_ADJ_FCTR = 0x36,
|
|
GEOMETRY_DESC_PARAM_ENM3_MAX_NUM_UNITS = 0x38,
|
|
GEOMETRY_DESC_PARAM_ENM3_CAP_ADJ_FCTR = 0x3C,
|
|
GEOMETRY_DESC_PARAM_ENM4_MAX_NUM_UNITS = 0x3E,
|
|
GEOMETRY_DESC_PARAM_ENM4_CAP_ADJ_FCTR = 0x42,
|
|
GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44,
|
|
GEOMETRY_DESC_PARAM_WB_MAX_ALLOC_UNITS = 0x4F,
|
|
GEOMETRY_DESC_PARAM_WB_MAX_WB_LUNS = 0x53,
|
|
GEOMETRY_DESC_PARAM_WB_BUFF_CAP_ADJ = 0x54,
|
|
GEOMETRY_DESC_PARAM_WB_SUP_RED_TYPE = 0x55,
|
|
GEOMETRY_DESC_PARAM_WB_SUP_WB_TYPE = 0x56,
|
|
};
|
|
|
|
/* Health descriptor parameters offsets in bytes*/
|
|
enum health_desc_param {
|
|
HEALTH_DESC_PARAM_LEN = 0x0,
|
|
HEALTH_DESC_PARAM_TYPE = 0x1,
|
|
HEALTH_DESC_PARAM_EOL_INFO = 0x2,
|
|
HEALTH_DESC_PARAM_LIFE_TIME_EST_A = 0x3,
|
|
HEALTH_DESC_PARAM_LIFE_TIME_EST_B = 0x4,
|
|
};
|
|
|
|
/* WriteBooster buffer mode */
|
|
enum {
|
|
WB_BUF_MODE_LU_DEDICATED = 0x0,
|
|
WB_BUF_MODE_SHARED = 0x1,
|
|
};
|
|
|
|
/*
|
|
* Logical Unit Write Protect
|
|
* 00h: LU not write protected
|
|
* 01h: LU write protected when fPowerOnWPEn =1
|
|
* 02h: LU permanently write protected when fPermanentWPEn =1
|
|
*/
|
|
enum ufs_lu_wp_type {
|
|
UFS_LU_NO_WP = 0x00,
|
|
UFS_LU_POWER_ON_WP = 0x01,
|
|
UFS_LU_PERM_WP = 0x02,
|
|
};
|
|
|
|
/* bActiveICCLevel parameter current units */
|
|
enum {
|
|
UFSHCD_NANO_AMP = 0,
|
|
UFSHCD_MICRO_AMP = 1,
|
|
UFSHCD_MILI_AMP = 2,
|
|
UFSHCD_AMP = 3,
|
|
};
|
|
|
|
/* Possible values for dExtendedUFSFeaturesSupport */
|
|
enum {
|
|
UFS_DEV_WRITE_BOOSTER_SUP = BIT(8),
|
|
};
|
|
|
|
#define POWER_DESC_MAX_SIZE 0x62
|
|
#define POWER_DESC_MAX_ACTV_ICC_LVLS 16
|
|
|
|
/* Attribute bActiveICCLevel parameter bit masks definitions */
|
|
#define ATTR_ICC_LVL_UNIT_OFFSET 14
|
|
#define ATTR_ICC_LVL_UNIT_MASK (0x3 << ATTR_ICC_LVL_UNIT_OFFSET)
|
|
#define ATTR_ICC_LVL_VALUE_MASK 0x3FF
|
|
|
|
/* Power descriptor parameters offsets in bytes */
|
|
enum power_desc_param_offset {
|
|
PWR_DESC_LEN = 0x0,
|
|
PWR_DESC_TYPE = 0x1,
|
|
PWR_DESC_ACTIVE_LVLS_VCC_0 = 0x2,
|
|
PWR_DESC_ACTIVE_LVLS_VCCQ_0 = 0x22,
|
|
PWR_DESC_ACTIVE_LVLS_VCCQ2_0 = 0x42,
|
|
};
|
|
|
|
/* Exception event mask values */
|
|
enum {
|
|
MASK_EE_STATUS = 0xFFFF,
|
|
MASK_EE_URGENT_BKOPS = (1 << 2),
|
|
};
|
|
|
|
/* Background operation status */
|
|
enum bkops_status {
|
|
BKOPS_STATUS_NO_OP = 0x0,
|
|
BKOPS_STATUS_NON_CRITICAL = 0x1,
|
|
BKOPS_STATUS_PERF_IMPACT = 0x2,
|
|
BKOPS_STATUS_CRITICAL = 0x3,
|
|
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
|
|
};
|
|
|
|
/* UTP QUERY Transaction Specific Fields OpCode */
|
|
enum query_opcode {
|
|
UPIU_QUERY_OPCODE_NOP = 0x0,
|
|
UPIU_QUERY_OPCODE_READ_DESC = 0x1,
|
|
UPIU_QUERY_OPCODE_WRITE_DESC = 0x2,
|
|
UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
|
|
UPIU_QUERY_OPCODE_WRITE_ATTR = 0x4,
|
|
UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
|
|
UPIU_QUERY_OPCODE_SET_FLAG = 0x6,
|
|
UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7,
|
|
UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8,
|
|
};
|
|
|
|
/* bRefClkFreq attribute values */
|
|
enum ufs_ref_clk_freq {
|
|
REF_CLK_FREQ_19_2_MHZ = 0,
|
|
REF_CLK_FREQ_26_MHZ = 1,
|
|
REF_CLK_FREQ_38_4_MHZ = 2,
|
|
REF_CLK_FREQ_52_MHZ = 3,
|
|
REF_CLK_FREQ_INVAL = -1,
|
|
};
|
|
|
|
struct ufs_ref_clk {
|
|
unsigned long freq_hz;
|
|
enum ufs_ref_clk_freq val;
|
|
};
|
|
|
|
/* Query response result code */
|
|
enum {
|
|
QUERY_RESULT_SUCCESS = 0x00,
|
|
QUERY_RESULT_NOT_READABLE = 0xF6,
|
|
QUERY_RESULT_NOT_WRITEABLE = 0xF7,
|
|
QUERY_RESULT_ALREADY_WRITTEN = 0xF8,
|
|
QUERY_RESULT_INVALID_LENGTH = 0xF9,
|
|
QUERY_RESULT_INVALID_VALUE = 0xFA,
|
|
QUERY_RESULT_INVALID_SELECTOR = 0xFB,
|
|
QUERY_RESULT_INVALID_INDEX = 0xFC,
|
|
QUERY_RESULT_INVALID_IDN = 0xFD,
|
|
QUERY_RESULT_INVALID_OPCODE = 0xFE,
|
|
QUERY_RESULT_GENERAL_FAILURE = 0xFF,
|
|
};
|
|
|
|
/* UTP Transfer Request Command Type (CT) */
|
|
enum {
|
|
UPIU_COMMAND_SET_TYPE_SCSI = 0x0,
|
|
UPIU_COMMAND_SET_TYPE_UFS = 0x1,
|
|
UPIU_COMMAND_SET_TYPE_QUERY = 0x2,
|
|
};
|
|
|
|
/* UTP Transfer Request Command Offset */
|
|
#define UPIU_COMMAND_TYPE_OFFSET 28
|
|
|
|
/* Offset of the response code in the UPIU header */
|
|
#define UPIU_RSP_CODE_OFFSET 8
|
|
|
|
enum {
|
|
MASK_SCSI_STATUS = 0xFF,
|
|
MASK_TASK_RESPONSE = 0xFF00,
|
|
MASK_RSP_UPIU_RESULT = 0xFFFF,
|
|
MASK_QUERY_DATA_SEG_LEN = 0xFFFF,
|
|
MASK_RSP_UPIU_DATA_SEG_LEN = 0xFFFF,
|
|
MASK_RSP_EXCEPTION_EVENT = 0x10000,
|
|
MASK_TM_SERVICE_RESP = 0xFF,
|
|
MASK_TM_FUNC = 0xFF,
|
|
};
|
|
|
|
/* Task management service response */
|
|
enum {
|
|
UPIU_TASK_MANAGEMENT_FUNC_COMPL = 0x00,
|
|
UPIU_TASK_MANAGEMENT_FUNC_NOT_SUPPORTED = 0x04,
|
|
UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED = 0x08,
|
|
UPIU_TASK_MANAGEMENT_FUNC_FAILED = 0x05,
|
|
UPIU_INCORRECT_LOGICAL_UNIT_NO = 0x09,
|
|
};
|
|
|
|
/* UFS device power modes */
|
|
enum ufs_dev_pwr_mode {
|
|
UFS_ACTIVE_PWR_MODE = 1,
|
|
UFS_SLEEP_PWR_MODE = 2,
|
|
UFS_POWERDOWN_PWR_MODE = 3,
|
|
};
|
|
|
|
#define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
|
|
|
|
/**
|
|
* struct utp_cmd_rsp - Response UPIU structure
|
|
* @residual_transfer_count: Residual transfer count DW-3
|
|
* @reserved: Reserved double words DW-4 to DW-7
|
|
* @sense_data_len: Sense data length DW-8 U16
|
|
* @sense_data: Sense data field DW-8 to DW-12
|
|
*/
|
|
struct utp_cmd_rsp {
|
|
__be32 residual_transfer_count;
|
|
__be32 reserved[4];
|
|
__be16 sense_data_len;
|
|
u8 sense_data[UFS_SENSE_SIZE];
|
|
};
|
|
|
|
/**
|
|
* struct utp_upiu_rsp - general upiu response structure
|
|
* @header: UPIU header structure DW-0 to DW-2
|
|
* @sr: fields structure for scsi command DW-3 to DW-12
|
|
* @qr: fields structure for query request DW-3 to DW-7
|
|
*/
|
|
struct utp_upiu_rsp {
|
|
struct utp_upiu_header header;
|
|
union {
|
|
struct utp_cmd_rsp sr;
|
|
struct utp_upiu_query qr;
|
|
};
|
|
};
|
|
|
|
/**
|
|
* struct ufs_query_req - parameters for building a query request
|
|
* @query_func: UPIU header query function
|
|
* @upiu_req: the query request data
|
|
*/
|
|
struct ufs_query_req {
|
|
u8 query_func;
|
|
struct utp_upiu_query upiu_req;
|
|
};
|
|
|
|
/**
|
|
* struct ufs_query_resp - UPIU QUERY
|
|
* @response: device response code
|
|
* @upiu_res: query response data
|
|
*/
|
|
struct ufs_query_res {
|
|
u8 response;
|
|
struct utp_upiu_query upiu_res;
|
|
};
|
|
|
|
#define UFS_VREG_VCC_MIN_UV 2700000 /* uV */
|
|
#define UFS_VREG_VCC_MAX_UV 3600000 /* uV */
|
|
#define UFS_VREG_VCC_1P8_MIN_UV 1700000 /* uV */
|
|
#define UFS_VREG_VCC_1P8_MAX_UV 1950000 /* uV */
|
|
#define UFS_VREG_VCCQ_MIN_UV 1140000 /* uV */
|
|
#define UFS_VREG_VCCQ_MAX_UV 1260000 /* uV */
|
|
#define UFS_VREG_VCCQ2_MIN_UV 1700000 /* uV */
|
|
#define UFS_VREG_VCCQ2_MAX_UV 1950000 /* uV */
|
|
|
|
/*
|
|
* VCCQ & VCCQ2 current requirement when UFS device is in sleep state
|
|
* and link is in Hibern8 state.
|
|
*/
|
|
#define UFS_VREG_LPM_LOAD_UA 1000 /* uA */
|
|
|
|
struct ufs_vreg {
|
|
struct regulator *reg;
|
|
const char *name;
|
|
bool enabled;
|
|
int min_uV;
|
|
int max_uV;
|
|
int max_uA;
|
|
};
|
|
|
|
struct ufs_vreg_info {
|
|
struct ufs_vreg *vcc;
|
|
struct ufs_vreg *vccq;
|
|
struct ufs_vreg *vccq2;
|
|
struct ufs_vreg *vdd_hba;
|
|
};
|
|
|
|
struct ufs_dev_info {
|
|
bool f_power_on_wp_en;
|
|
/* Keeps information if any of the LU is power on write protected */
|
|
bool is_lu_power_on_wp;
|
|
/* Maximum number of general LU supported by the UFS device */
|
|
u8 max_lu_supported;
|
|
u8 wb_dedicated_lu;
|
|
u16 wmanufacturerid;
|
|
/*UFS device Product Name */
|
|
u8 *model;
|
|
u16 wspecversion;
|
|
u32 clk_gating_wait_us;
|
|
u32 d_ext_ufs_feature_sup;
|
|
u8 b_wb_buffer_type;
|
|
u32 d_wb_alloc_units;
|
|
bool b_rpm_dev_flush_capable;
|
|
u8 b_presrv_uspc_en;
|
|
};
|
|
|
|
/**
|
|
* ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
|
|
* @dev_info: pointer of instance of struct ufs_dev_info
|
|
* @lun: LU number to check
|
|
* @return: true if the lun has a matching unit descriptor, false otherwise
|
|
*/
|
|
static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info,
|
|
u8 lun)
|
|
{
|
|
if (!dev_info || !dev_info->max_lu_supported) {
|
|
pr_err("Max General LU supported by UFS isn't initialized\n");
|
|
return false;
|
|
}
|
|
|
|
return lun == UFS_UPIU_RPMB_WLUN || (lun < dev_info->max_lu_supported);
|
|
}
|
|
|
|
#endif /* End of Header */
|