OpenCloudOS-Kernel/drivers/scsi/ufs/ufs.h

565 lines
16 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Universal Flash Storage Host controller driver
* Copyright (C) 2011-2013 Samsung India Software Operations
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
* Vinayak Holikatti <h.vinayak@samsung.com>
*/
#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)
#define UFS_RPMB_UNIT 0xC4
2020-05-08 16:01:13 +08:00
/* 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,
};
/* 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,
};
2020-05-08 16:01:13 +08:00
/* WriteBooster buffer mode */
enum {
WB_BUF_MODE_LU_DEDICATED = 0x0,
WB_BUF_MODE_SHARED = 0x1,
};
ufs: add UFS power management support This patch adds support for UFS device and UniPro link power management during runtime/system PM. Main idea is to define multiple UFS low power levels based on UFS device and UFS link power states. This would allow any specific platform or pci driver to choose the best suited low power level during runtime and system suspend based on their power goals. bkops handlig: To put the UFS device in sleep state when bkops is disabled, first query the bkops status from the device and enable bkops on device only if device needs time to perform the bkops. START_STOP handling: Before sending START_STOP_UNIT to the device well-known logical unit (w-lun) to make sure that the device w-lun unit attention condition is cleared. Write protection: UFS device specification allows LUs to be write protected, either permanently or power on write protected. If any LU is power on write protected and if the card is power cycled (by powering off VCCQ and/or VCC rails), LU's write protect status would be lost. So this means those LUs can be written now. To ensures that UFS device is power cycled only if the power on protect is not set for any of the LUs, check if power on write protect is set and if device is in sleep/power-off state & link in inactive state (Hibern8 or OFF state). If none of the Logical Units on UFS device is power on write protected then all UFS device power rails (VCC, VCCQ & VCCQ2) can be turned off if UFS device is in power-off state and UFS link is in OFF state. But current implementation would disable all device power rails even if UFS link is not in OFF state. Low power mode: If UFS link is in OFF state then UFS host controller can be power collapsed to avoid leakage current from it. Note that if UFS host controller is power collapsed, full UFS reinitialization will be required on resume to re-establish the link between host and device. Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
2014-09-25 20:32:30 +08:00
/*
* 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 */
ufs: add UFS power management support This patch adds support for UFS device and UniPro link power management during runtime/system PM. Main idea is to define multiple UFS low power levels based on UFS device and UFS link power states. This would allow any specific platform or pci driver to choose the best suited low power level during runtime and system suspend based on their power goals. bkops handlig: To put the UFS device in sleep state when bkops is disabled, first query the bkops status from the device and enable bkops on device only if device needs time to perform the bkops. START_STOP handling: Before sending START_STOP_UNIT to the device well-known logical unit (w-lun) to make sure that the device w-lun unit attention condition is cleared. Write protection: UFS device specification allows LUs to be write protected, either permanently or power on write protected. If any LU is power on write protected and if the card is power cycled (by powering off VCCQ and/or VCC rails), LU's write protect status would be lost. So this means those LUs can be written now. To ensures that UFS device is power cycled only if the power on protect is not set for any of the LUs, check if power on write protect is set and if device is in sleep/power-off state & link in inactive state (Hibern8 or OFF state). If none of the Logical Units on UFS device is power on write protected then all UFS device power rails (VCC, VCCQ & VCCQ2) can be turned off if UFS device is in power-off state and UFS link is in OFF state. But current implementation would disable all device power rails even if UFS link is not in OFF state. Low power mode: If UFS link is in OFF state then UFS host controller can be power collapsed to avoid leakage current from it. Note that if UFS host controller is power collapsed, full UFS reinitialization will be required on resume to re-establish the link between host and device. Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
2014-09-25 20:32:30 +08:00
enum bkops_status {
BKOPS_STATUS_NO_OP = 0x0,
BKOPS_STATUS_NON_CRITICAL = 0x1,
BKOPS_STATUS_PERF_IMPACT = 0x2,
BKOPS_STATUS_CRITICAL = 0x3,
ufs: add UFS power management support This patch adds support for UFS device and UniPro link power management during runtime/system PM. Main idea is to define multiple UFS low power levels based on UFS device and UFS link power states. This would allow any specific platform or pci driver to choose the best suited low power level during runtime and system suspend based on their power goals. bkops handlig: To put the UFS device in sleep state when bkops is disabled, first query the bkops status from the device and enable bkops on device only if device needs time to perform the bkops. START_STOP handling: Before sending START_STOP_UNIT to the device well-known logical unit (w-lun) to make sure that the device w-lun unit attention condition is cleared. Write protection: UFS device specification allows LUs to be write protected, either permanently or power on write protected. If any LU is power on write protected and if the card is power cycled (by powering off VCCQ and/or VCC rails), LU's write protect status would be lost. So this means those LUs can be written now. To ensures that UFS device is power cycled only if the power on protect is not set for any of the LUs, check if power on write protect is set and if device is in sleep/power-off state & link in inactive state (Hibern8 or OFF state). If none of the Logical Units on UFS device is power on write protected then all UFS device power rails (VCC, VCCQ & VCCQ2) can be turned off if UFS device is in power-off state and UFS link is in OFF state. But current implementation would disable all device power rails even if UFS link is not in OFF state. Low power mode: If UFS link is in OFF state then UFS host controller can be power collapsed to avoid leakage current from it. Note that if UFS host controller is power collapsed, full UFS reinitialization will be required on resume to re-establish the link between host and device. Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
2014-09-25 20:32:30 +08:00
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: add UFS power management support This patch adds support for UFS device and UniPro link power management during runtime/system PM. Main idea is to define multiple UFS low power levels based on UFS device and UFS link power states. This would allow any specific platform or pci driver to choose the best suited low power level during runtime and system suspend based on their power goals. bkops handlig: To put the UFS device in sleep state when bkops is disabled, first query the bkops status from the device and enable bkops on device only if device needs time to perform the bkops. START_STOP handling: Before sending START_STOP_UNIT to the device well-known logical unit (w-lun) to make sure that the device w-lun unit attention condition is cleared. Write protection: UFS device specification allows LUs to be write protected, either permanently or power on write protected. If any LU is power on write protected and if the card is power cycled (by powering off VCCQ and/or VCC rails), LU's write protect status would be lost. So this means those LUs can be written now. To ensures that UFS device is power cycled only if the power on protect is not set for any of the LUs, check if power on write protect is set and if device is in sleep/power-off state & link in inactive state (Hibern8 or OFF state). If none of the Logical Units on UFS device is power on write protected then all UFS device power rails (VCC, VCCQ & VCCQ2) can be turned off if UFS device is in power-off state and UFS link is in OFF state. But current implementation would disable all device power rails even if UFS link is not in OFF state. Low power mode: If UFS link is in OFF state then UFS host controller can be power collapsed to avoid leakage current from it. Note that if UFS host controller is power collapsed, full UFS reinitialization will be required on resume to re-establish the link between host and device. Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
2014-09-25 20:32:30 +08:00
/* 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 */
ufs: add UFS power management support This patch adds support for UFS device and UniPro link power management during runtime/system PM. Main idea is to define multiple UFS low power levels based on UFS device and UFS link power states. This would allow any specific platform or pci driver to choose the best suited low power level during runtime and system suspend based on their power goals. bkops handlig: To put the UFS device in sleep state when bkops is disabled, first query the bkops status from the device and enable bkops on device only if device needs time to perform the bkops. START_STOP handling: Before sending START_STOP_UNIT to the device well-known logical unit (w-lun) to make sure that the device w-lun unit attention condition is cleared. Write protection: UFS device specification allows LUs to be write protected, either permanently or power on write protected. If any LU is power on write protected and if the card is power cycled (by powering off VCCQ and/or VCC rails), LU's write protect status would be lost. So this means those LUs can be written now. To ensures that UFS device is power cycled only if the power on protect is not set for any of the LUs, check if power on write protect is set and if device is in sleep/power-off state & link in inactive state (Hibern8 or OFF state). If none of the Logical Units on UFS device is power on write protected then all UFS device power rails (VCC, VCCQ & VCCQ2) can be turned off if UFS device is in power-off state and UFS link is in OFF state. But current implementation would disable all device power rails even if UFS link is not in OFF state. Low power mode: If UFS link is in OFF state then UFS host controller can be power collapsed to avoid leakage current from it. Note that if UFS host controller is power collapsed, full UFS reinitialization will be required on resume to re-establish the link between host and device. Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
2014-09-25 20:32:30 +08:00
/*
* 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;
};
ufs: add UFS power management support This patch adds support for UFS device and UniPro link power management during runtime/system PM. Main idea is to define multiple UFS low power levels based on UFS device and UFS link power states. This would allow any specific platform or pci driver to choose the best suited low power level during runtime and system suspend based on their power goals. bkops handlig: To put the UFS device in sleep state when bkops is disabled, first query the bkops status from the device and enable bkops on device only if device needs time to perform the bkops. START_STOP handling: Before sending START_STOP_UNIT to the device well-known logical unit (w-lun) to make sure that the device w-lun unit attention condition is cleared. Write protection: UFS device specification allows LUs to be write protected, either permanently or power on write protected. If any LU is power on write protected and if the card is power cycled (by powering off VCCQ and/or VCC rails), LU's write protect status would be lost. So this means those LUs can be written now. To ensures that UFS device is power cycled only if the power on protect is not set for any of the LUs, check if power on write protect is set and if device is in sleep/power-off state & link in inactive state (Hibern8 or OFF state). If none of the Logical Units on UFS device is power on write protected then all UFS device power rails (VCC, VCCQ & VCCQ2) can be turned off if UFS device is in power-off state and UFS link is in OFF state. But current implementation would disable all device power rails even if UFS link is not in OFF state. Low power mode: If UFS link is in OFF state then UFS host controller can be power collapsed to avoid leakage current from it. Note that if UFS host controller is power collapsed, full UFS reinitialization will be required on resume to re-establish the link between host and device. Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
2014-09-25 20:32:30 +08:00
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;
2020-05-08 16:01:13 +08:00
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;
scsi: ufs: Fix WriteBooster flush during runtime suspend 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>
2020-05-22 16:32:12 +08:00
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 */