ufs: Add Initial Support for UFS subsystem

Add Support for UFS Host Controller Interface (UFSHCI) for communicating
with Universal Flash Storage (UFS) devices. The steps to initialize the
host controller interface are the following:

- Initiate the Host Controller Initialization process by writing to the
Host controller enable register.
- Configure the Host Controller base address registers by allocating a
host memory space and related data structures.
- Unipro link startup procedure
- Check for connected device
- Configure UFS host controller to process requests

Also register this host controller as a SCSI host controller.

Taken from Linux Kernel v5.2 (drivers/scsi/ufs/ufshcd.c) and ported to
U-boot.

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
This commit is contained in:
Faiz Abbas 2019-10-15 18:24:36 +05:30 committed by Tom Rini
parent 8fbac8e23e
commit 7feafb0ae4
11 changed files with 3225 additions and 0 deletions

View File

@ -840,6 +840,11 @@ S: Maintained
T: git https://gitlab.denx.de/u-boot/custodians/u-boot-ubi.git
F: drivers/mtd/ubi/
UFS
M: Faiz Abbas <faiz_abbas@ti.com>
S: Maintained
F: drivers/ufs/
USB
M: Marek Vasut <marex@denx.de>
S: Maintained

View File

@ -118,6 +118,8 @@ source "drivers/tpm/Kconfig"
source "drivers/usb/Kconfig"
source "drivers/ufs/Kconfig"
source "drivers/video/Kconfig"
source "drivers/virtio/Kconfig"

View File

@ -111,6 +111,7 @@ obj-y += soc/
obj-y += thermal/
obj-$(CONFIG_TEE) += tee/
obj-y += axi/
obj-y += ufs/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_W1_EEPROM) += w1-eeprom/

9
drivers/ufs/Kconfig Normal file
View File

@ -0,0 +1,9 @@
menu "UFS Host Controller Support"
config UFS
bool "Support UFS controllers"
depends on DM_SCSI
help
This selects support for Universal Flash Subsystem (UFS).
Say Y here if you want UFS Support.
endmenu

6
drivers/ufs/Makefile Normal file
View File

@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
#
obj-$(CONFIG_UFS) += ufs.o ufs-uclass.o

16
drivers/ufs/ufs-uclass.c Normal file
View File

@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
/**
* ufs-uclass.c - Universal Flash Subsystem (UFS) Uclass driver
*
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
*/
#include <common.h>
#include "ufs.h"
#include <dm.h>
UCLASS_DRIVER(ufs) = {
.id = UCLASS_UFS,
.name = "ufs",
.per_device_auto_alloc_size = sizeof(struct ufs_hba),
};

1968
drivers/ufs/ufs.c Normal file

File diff suppressed because it is too large Load Diff

918
drivers/ufs/ufs.h Normal file
View File

@ -0,0 +1,918 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __UFS_H
#define __UFS_H
#include <asm/io.h>
#include <dm.h>
#include "unipro.h"
#define UFS_CDB_SIZE 16
#define UPIU_TRANSACTION_UIC_CMD 0x1F
#define UIC_CMD_SIZE (sizeof(u32) * 4)
#define RESPONSE_UPIU_SENSE_DATA_LENGTH 18
#define UFS_MAX_LUNS 0x7F
enum {
TASK_REQ_UPIU_SIZE_DWORDS = 8,
TASK_RSP_UPIU_SIZE_DWORDS = 8,
ALIGNED_UPIU_SIZE = 512,
};
/* UFS device power modes */
enum ufs_dev_pwr_mode {
UFS_ACTIVE_PWR_MODE = 1,
UFS_SLEEP_PWR_MODE = 2,
UFS_POWERDOWN_PWR_MODE = 3,
};
enum ufs_notify_change_status {
PRE_CHANGE,
POST_CHANGE,
};
struct ufs_pa_layer_attr {
u32 gear_rx;
u32 gear_tx;
u32 lane_rx;
u32 lane_tx;
u32 pwr_rx;
u32 pwr_tx;
u32 hs_rate;
};
struct ufs_pwr_mode_info {
bool is_valid;
struct ufs_pa_layer_attr info;
};
enum ufs_desc_def_size {
QUERY_DESC_DEVICE_DEF_SIZE = 0x40,
QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90,
QUERY_DESC_UNIT_DEF_SIZE = 0x23,
QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06,
QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48,
QUERY_DESC_POWER_DEF_SIZE = 0x62,
QUERY_DESC_HEALTH_DEF_SIZE = 0x25,
};
struct ufs_desc_size {
int dev_desc;
int pwr_desc;
int geom_desc;
int interc_desc;
int unit_desc;
int conf_desc;
int hlth_desc;
};
/*
* Request Descriptor Definitions
*/
/* Transfer request command type */
enum {
UTP_CMD_TYPE_SCSI = 0x0,
UTP_CMD_TYPE_UFS = 0x1,
UTP_CMD_TYPE_DEV_MANAGE = 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
/* To accommodate UFS2.0 required Command type */
enum {
UTP_CMD_TYPE_UFS_STORAGE = 0x1,
};
enum {
UTP_SCSI_COMMAND = 0x00000000,
UTP_NATIVE_UFS_COMMAND = 0x10000000,
UTP_DEVICE_MANAGEMENT_FUNCTION = 0x20000000,
UTP_REQ_DESC_INT_CMD = 0x01000000,
};
/* UTP Transfer Request Data Direction (DD) */
enum {
UTP_NO_DATA_TRANSFER = 0x00000000,
UTP_HOST_TO_DEVICE = 0x02000000,
UTP_DEVICE_TO_HOST = 0x04000000,
};
/* Overall command status values */
enum {
OCS_SUCCESS = 0x0,
OCS_INVALID_CMD_TABLE_ATTR = 0x1,
OCS_INVALID_PRDT_ATTR = 0x2,
OCS_MISMATCH_DATA_BUF_SIZE = 0x3,
OCS_MISMATCH_RESP_UPIU_SIZE = 0x4,
OCS_PEER_COMM_FAILURE = 0x5,
OCS_ABORTED = 0x6,
OCS_FATAL_ERROR = 0x7,
OCS_INVALID_COMMAND_STATUS = 0x0F,
MASK_OCS = 0x0F,
};
/* The maximum length of the data byte count field in the PRDT is 256KB */
#define PRDT_DATA_BYTE_COUNT_MAX (256 * 1024)
/* The granularity of the data byte count field in the PRDT is 32-bit */
#define PRDT_DATA_BYTE_COUNT_PAD 4
#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 RESPONSE_UPIU_SENSE_DATA_LENGTH 18
#define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
(byte1 << 8) | (byte0))
/*
* 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,
};
/* 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,
};
/* 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,
};
/* 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,
};
enum {
UPIU_COMMAND_SET_TYPE_SCSI = 0x0,
UPIU_COMMAND_SET_TYPE_UFS = 0x1,
UPIU_COMMAND_SET_TYPE_QUERY = 0x2,
};
/* 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,
};
/* 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,
};
/* 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,
};
struct ufshcd_sg_entry {
__le32 base_addr;
__le32 upper_addr;
__le32 reserved;
__le32 size;
};
#define MAX_BUFF 128
/**
* struct utp_transfer_cmd_desc - UFS Command Descriptor structure
* @command_upiu: Command UPIU Frame address
* @response_upiu: Response UPIU Frame address
* @prd_table: Physical Region Descriptor
*/
struct utp_transfer_cmd_desc {
u8 command_upiu[ALIGNED_UPIU_SIZE];
u8 response_upiu[ALIGNED_UPIU_SIZE];
struct ufshcd_sg_entry prd_table[MAX_BUFF];
};
/**
* struct request_desc_header - Descriptor Header common to both UTRD and UTMRD
* @dword0: Descriptor Header DW0
* @dword1: Descriptor Header DW1
* @dword2: Descriptor Header DW2
* @dword3: Descriptor Header DW3
*/
struct request_desc_header {
__le32 dword_0;
__le32 dword_1;
__le32 dword_2;
__le32 dword_3;
};
/**
* struct utp_transfer_req_desc - UTRD structure
* @header: UTRD header DW-0 to DW-3
* @command_desc_base_addr_lo: UCD base address low DW-4
* @command_desc_base_addr_hi: UCD base address high DW-5
* @response_upiu_length: response UPIU length DW-6
* @response_upiu_offset: response UPIU offset DW-6
* @prd_table_length: Physical region descriptor length DW-7
* @prd_table_offset: Physical region descriptor offset DW-7
*/
struct utp_transfer_req_desc {
/* DW 0-3 */
struct request_desc_header header;
/* DW 4-5*/
__le32 command_desc_base_addr_lo;
__le32 command_desc_base_addr_hi;
/* DW 6 */
__le16 response_upiu_length;
__le16 response_upiu_offset;
/* DW 7 */
__le16 prd_table_length;
__le16 prd_table_offset;
};
/**
* struct utp_upiu_header - UPIU header structure
* @dword_0: UPIU header DW-0
* @dword_1: UPIU header DW-1
* @dword_2: UPIU header DW-2
*/
struct utp_upiu_header {
__be32 dword_0;
__be32 dword_1;
__be32 dword_2;
};
/**
* struct utp_upiu_query - upiu request buffer structure for
* query request.
* @opcode: command to perform B-0
* @idn: a value that indicates the particular type of data B-1
* @index: Index to further identify data B-2
* @selector: Index to further identify data B-3
* @reserved_osf: spec reserved field B-4,5
* @length: number of descriptor bytes to read/write B-6,7
* @value: Attribute value to be written DW-5
* @reserved: spec reserved DW-6,7
*/
struct utp_upiu_query {
__u8 opcode;
__u8 idn;
__u8 index;
__u8 selector;
__be16 reserved_osf;
__be16 length;
__be32 value;
__be32 reserved[2];
};
/**
* struct utp_upiu_cmd - Command UPIU structure
* @data_transfer_len: Data Transfer Length DW-3
* @cdb: Command Descriptor Block CDB DW-4 to DW-7
*/
struct utp_upiu_cmd {
__be32 exp_data_transfer_len;
u8 cdb[UFS_CDB_SIZE];
};
/*
* UTMRD structure.
*/
struct utp_task_req_desc {
/* DW 0-3 */
struct request_desc_header header;
/* DW 4-11 - Task request UPIU structure */
struct utp_upiu_header req_header;
__be32 input_param1;
__be32 input_param2;
__be32 input_param3;
__be32 __reserved1[2];
/* DW 12-19 - Task Management Response UPIU structure */
struct utp_upiu_header rsp_header;
__be32 output_param1;
__be32 output_param2;
__be32 __reserved2[3];
};
/**
* struct utp_upiu_req - general upiu request structure
* @header:UPIU header structure DW-0 to DW-2
* @sc: fields structure for scsi command DW-3 to DW-7
* @qr: fields structure for query request DW-3 to DW-7
*/
struct utp_upiu_req {
struct utp_upiu_header header;
union {
struct utp_upiu_cmd sc;
struct utp_upiu_query qr;
struct utp_upiu_query tr;
/* use utp_upiu_query to host the 4 dwords of uic command */
struct utp_upiu_query uc;
};
};
/**
* 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[RESPONSE_UPIU_SENSE_DATA_LENGTH];
};
/**
* 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;
};
};
#define MAX_MODEL_LEN 16
/**
* ufs_dev_desc - ufs device details from the device descriptor
*
* @wmanufacturerid: card details
* @model: card model
*/
struct ufs_dev_desc {
u16 wmanufacturerid;
char model[MAX_MODEL_LEN + 1];
};
/* 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,
};
struct ufs_hba;
enum {
UFSHCD_MAX_CHANNEL = 0,
UFSHCD_MAX_ID = 1,
};
enum dev_cmd_type {
DEV_CMD_TYPE_NOP = 0x0,
DEV_CMD_TYPE_QUERY = 0x1,
};
/**
* struct uic_command - UIC command structure
* @command: UIC command
* @argument1: UIC command argument 1
* @argument2: UIC command argument 2
* @argument3: UIC command argument 3
* @cmd_active: Indicate if UIC command is outstanding
* @result: UIC command result
* @done: UIC command completion
*/
struct uic_command {
u32 command;
u32 argument1;
u32 argument2;
u32 argument3;
int cmd_active;
int result;
};
/* GenSelectorIndex calculation macros for M-PHY attributes */
#define UIC_ARG_MPHY_TX_GEN_SEL_INDEX(lane) (lane)
#define UIC_ARG_MPHY_RX_GEN_SEL_INDEX(lane) (PA_MAXDATALANES + (lane))
#define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\
((sel) & 0xFFFF))
#define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0)
#define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16)
#define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF)
/* Link Status*/
enum link_status {
UFSHCD_LINK_IS_DOWN = 1,
UFSHCD_LINK_IS_UP = 2,
};
#define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\
((sel) & 0xFFFF))
#define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0)
#define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16)
#define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF)
/* UIC Commands */
enum uic_cmd_dme {
UIC_CMD_DME_GET = 0x01,
UIC_CMD_DME_SET = 0x02,
UIC_CMD_DME_PEER_GET = 0x03,
UIC_CMD_DME_PEER_SET = 0x04,
UIC_CMD_DME_POWERON = 0x10,
UIC_CMD_DME_POWEROFF = 0x11,
UIC_CMD_DME_ENABLE = 0x12,
UIC_CMD_DME_RESET = 0x14,
UIC_CMD_DME_END_PT_RST = 0x15,
UIC_CMD_DME_LINK_STARTUP = 0x16,
UIC_CMD_DME_HIBER_ENTER = 0x17,
UIC_CMD_DME_HIBER_EXIT = 0x18,
UIC_CMD_DME_TEST_MODE = 0x1A,
};
/* UIC Config result code / Generic error code */
enum {
UIC_CMD_RESULT_SUCCESS = 0x00,
UIC_CMD_RESULT_INVALID_ATTR = 0x01,
UIC_CMD_RESULT_FAILURE = 0x01,
UIC_CMD_RESULT_INVALID_ATTR_VALUE = 0x02,
UIC_CMD_RESULT_READ_ONLY_ATTR = 0x03,
UIC_CMD_RESULT_WRITE_ONLY_ATTR = 0x04,
UIC_CMD_RESULT_BAD_INDEX = 0x05,
UIC_CMD_RESULT_LOCKED_ATTR = 0x06,
UIC_CMD_RESULT_BAD_TEST_FEATURE_INDEX = 0x07,
UIC_CMD_RESULT_PEER_COMM_FAILURE = 0x08,
UIC_CMD_RESULT_BUSY = 0x09,
UIC_CMD_RESULT_DME_FAILURE = 0x0A,
};
#define MASK_UIC_COMMAND_RESULT 0xFF
/* Host <-> Device UniPro Link state */
enum uic_link_state {
UIC_LINK_OFF_STATE = 0, /* Link powered down or disabled */
UIC_LINK_ACTIVE_STATE = 1, /* Link is in Fast/Slow/Sleep state */
UIC_LINK_HIBERN8_STATE = 2, /* Link is in Hibernate state */
};
/* UIC command interfaces for DME primitives */
#define DME_LOCAL 0
#define DME_PEER 1
#define ATTR_SET_NOR 0 /* NORMAL */
#define ATTR_SET_ST 1 /* STATIC */
int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
u8 attr_set, u32 mib_val, u8 peer);
int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
u32 *mib_val, u8 peer);
static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
u32 mib_val)
{
return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
mib_val, DME_LOCAL);
}
static inline int ufshcd_dme_get(struct ufs_hba *hba,
u32 attr_sel, u32 *mib_val)
{
return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL);
}
static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
u32 attr_sel, u32 *mib_val)
{
return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
}
static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
u32 mib_val)
{
return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
mib_val, DME_PEER);
}
/**
* 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;
};
/**
* struct ufs_query - holds relevant data structures for query request
* @request: request upiu and function
* @descriptor: buffer for sending/receiving descriptor
* @response: response upiu and response
*/
struct ufs_query {
struct ufs_query_req request;
u8 *descriptor;
struct ufs_query_res response;
};
/**
* struct ufs_dev_cmd - all assosiated fields with device management commands
* @type: device management command type - Query, NOP OUT
* @tag_wq: wait queue until free command slot is available
*/
struct ufs_dev_cmd {
enum dev_cmd_type type;
struct ufs_query query;
};
struct ufs_hba_ops {
int (*init)(struct ufs_hba *hba);
int (*hce_enable_notify)(struct ufs_hba *hba,
enum ufs_notify_change_status);
int (*link_startup_notify)(struct ufs_hba *hba,
enum ufs_notify_change_status);
int (*phy_initialization)(struct ufs_hba *hba);
};
struct ufs_hba {
struct udevice *dev;
void __iomem *mmio_base;
struct ufs_hba_ops *ops;
struct ufs_desc_size desc_size;
u32 capabilities;
u32 version;
u32 intr_mask;
u32 quirks;
/*
* If UFS host controller is having issue in processing LCC (Line
* Control Command) coming from device then enable this quirk.
* When this quirk is enabled, host controller driver should disable
* the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
* attribute of device to 0).
*/
#define UFSHCD_QUIRK_BROKEN_LCC 0x1
/* Virtual memory reference */
struct utp_transfer_cmd_desc *ucdl;
struct utp_transfer_req_desc *utrdl;
/* TODO: Add Task Manegement Support */
struct utp_task_req_desc *utmrdl;
struct utp_upiu_req *ucd_req_ptr;
struct utp_upiu_rsp *ucd_rsp_ptr;
struct ufshcd_sg_entry *ucd_prdt_ptr;
/* Power Mode information */
enum ufs_dev_pwr_mode curr_dev_pwr_mode;
struct ufs_pa_layer_attr pwr_info;
struct ufs_pwr_mode_info max_pwr_info;
struct ufs_dev_cmd dev_cmd;
};
static inline int ufshcd_ops_init(struct ufs_hba *hba)
{
if (hba->ops && hba->ops->init)
return hba->ops->init(hba);
return 0;
}
static inline int ufshcd_ops_hce_enable_notify(struct ufs_hba *hba,
bool status)
{
if (hba->ops && hba->ops->hce_enable_notify)
return hba->ops->hce_enable_notify(hba, status);
return 0;
}
static inline int ufshcd_ops_link_startup_notify(struct ufs_hba *hba,
bool status)
{
if (hba->ops && hba->ops->link_startup_notify)
return hba->ops->link_startup_notify(hba, status);
return 0;
}
/* Controller UFSHCI version */
enum {
UFSHCI_VERSION_10 = 0x00010000, /* 1.0 */
UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */
UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */
UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */
};
/* Interrupt disable masks */
enum {
/* Interrupt disable mask for UFSHCI v1.0 */
INTERRUPT_MASK_ALL_VER_10 = 0x30FFF,
INTERRUPT_MASK_RW_VER_10 = 0x30000,
/* Interrupt disable mask for UFSHCI v1.1 */
INTERRUPT_MASK_ALL_VER_11 = 0x31FFF,
/* Interrupt disable mask for UFSHCI v2.1 */
INTERRUPT_MASK_ALL_VER_21 = 0x71FFF,
};
/* UFSHCI Registers */
enum {
REG_CONTROLLER_CAPABILITIES = 0x00,
REG_UFS_VERSION = 0x08,
REG_CONTROLLER_DEV_ID = 0x10,
REG_CONTROLLER_PROD_ID = 0x14,
REG_AUTO_HIBERNATE_IDLE_TIMER = 0x18,
REG_INTERRUPT_STATUS = 0x20,
REG_INTERRUPT_ENABLE = 0x24,
REG_CONTROLLER_STATUS = 0x30,
REG_CONTROLLER_ENABLE = 0x34,
REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER = 0x38,
REG_UIC_ERROR_CODE_DATA_LINK_LAYER = 0x3C,
REG_UIC_ERROR_CODE_NETWORK_LAYER = 0x40,
REG_UIC_ERROR_CODE_TRANSPORT_LAYER = 0x44,
REG_UIC_ERROR_CODE_DME = 0x48,
REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL = 0x4C,
REG_UTP_TRANSFER_REQ_LIST_BASE_L = 0x50,
REG_UTP_TRANSFER_REQ_LIST_BASE_H = 0x54,
REG_UTP_TRANSFER_REQ_DOOR_BELL = 0x58,
REG_UTP_TRANSFER_REQ_LIST_CLEAR = 0x5C,
REG_UTP_TRANSFER_REQ_LIST_RUN_STOP = 0x60,
REG_UTP_TASK_REQ_LIST_BASE_L = 0x70,
REG_UTP_TASK_REQ_LIST_BASE_H = 0x74,
REG_UTP_TASK_REQ_DOOR_BELL = 0x78,
REG_UTP_TASK_REQ_LIST_CLEAR = 0x7C,
REG_UTP_TASK_REQ_LIST_RUN_STOP = 0x80,
REG_UIC_COMMAND = 0x90,
REG_UIC_COMMAND_ARG_1 = 0x94,
REG_UIC_COMMAND_ARG_2 = 0x98,
REG_UIC_COMMAND_ARG_3 = 0x9C,
UFSHCI_REG_SPACE_SIZE = 0xA0,
REG_UFS_CCAP = 0x100,
REG_UFS_CRYPTOCAP = 0x104,
UFSHCI_CRYPTO_REG_SPACE_SIZE = 0x400,
};
/* Controller capability masks */
enum {
MASK_TRANSFER_REQUESTS_SLOTS = 0x0000001F,
MASK_TASK_MANAGEMENT_REQUEST_SLOTS = 0x00070000,
MASK_AUTO_HIBERN8_SUPPORT = 0x00800000,
MASK_64_ADDRESSING_SUPPORT = 0x01000000,
MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000,
MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000,
};
/* Interrupt Status 20h */
#define UTP_TRANSFER_REQ_COMPL 0x1
#define UIC_DME_END_PT_RESET 0x2
#define UIC_ERROR 0x4
#define UIC_TEST_MODE 0x8
#define UIC_POWER_MODE 0x10
#define UIC_HIBERNATE_EXIT 0x20
#define UIC_HIBERNATE_ENTER 0x40
#define UIC_LINK_LOST 0x80
#define UIC_LINK_STARTUP 0x100
#define UTP_TASK_REQ_COMPL 0x200
#define UIC_COMMAND_COMPL 0x400
#define DEVICE_FATAL_ERROR 0x800
#define CONTROLLER_FATAL_ERROR 0x10000
#define SYSTEM_BUS_FATAL_ERROR 0x20000
#define UFSHCD_UIC_PWR_MASK (UIC_HIBERNATE_ENTER |\
UIC_HIBERNATE_EXIT |\
UIC_POWER_MODE)
#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL | UIC_POWER_MODE)
#define UFSHCD_ERROR_MASK (UIC_ERROR |\
DEVICE_FATAL_ERROR |\
CONTROLLER_FATAL_ERROR |\
SYSTEM_BUS_FATAL_ERROR)
#define INT_FATAL_ERRORS (DEVICE_FATAL_ERROR |\
CONTROLLER_FATAL_ERROR |\
SYSTEM_BUS_FATAL_ERROR)
/* Host Controller Enable 0x34h */
#define CONTROLLER_ENABLE 0x1
#define CONTROLLER_DISABLE 0x0
/* HCS - Host Controller Status 30h */
#define DEVICE_PRESENT 0x1
#define UTP_TRANSFER_REQ_LIST_READY 0x2
#define UTP_TASK_REQ_LIST_READY 0x4
#define UIC_COMMAND_READY 0x8
#define HOST_ERROR_INDICATOR 0x10
#define DEVICE_ERROR_INDICATOR 0x20
#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8)
#define UFSHCD_STATUS_READY (UTP_TRANSFER_REQ_LIST_READY |\
UTP_TASK_REQ_LIST_READY |\
UIC_COMMAND_READY)
enum {
PWR_OK = 0x0,
PWR_LOCAL = 0x01,
PWR_REMOTE = 0x02,
PWR_BUSY = 0x03,
PWR_ERROR_CAP = 0x04,
PWR_FATAL_ERROR = 0x05,
};
/* UICCMD - UIC Command */
#define COMMAND_OPCODE_MASK 0xFF
#define GEN_SELECTOR_INDEX_MASK 0xFFFF
#define MIB_ATTRIBUTE_MASK UFS_MASK(0xFFFF, 16)
#define RESET_LEVEL 0xFF
#define ATTR_SET_TYPE_MASK UFS_MASK(0xFF, 16)
#define CONFIG_RESULT_CODE_MASK 0xFF
#define GENERIC_ERROR_CODE_MASK 0xFF
#define ufshcd_writel(hba, val, reg) \
writel((val), (hba)->mmio_base + (reg))
#define ufshcd_readl(hba, reg) \
readl((hba)->mmio_base + (reg))
/* UTRLRSR - UTP Transfer Request Run-Stop Register 60h */
#define UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT 0x1
/* UTMRLRSR - UTP Task Management Request Run-Stop Register 80h */
#define UTP_TASK_REQ_LIST_RUN_STOP_BIT 0x1
int ufshcd_probe(struct udevice *dev, struct ufs_hba_ops *hba_ops);
#endif

270
drivers/ufs/unipro.h Normal file
View File

@ -0,0 +1,270 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef _UNIPRO_H_
#define _UNIPRO_H_
/*
* M-TX Configuration Attributes
*/
#define TX_HIBERN8TIME_CAPABILITY 0x000F
#define TX_MODE 0x0021
#define TX_HSRATE_SERIES 0x0022
#define TX_HSGEAR 0x0023
#define TX_PWMGEAR 0x0024
#define TX_AMPLITUDE 0x0025
#define TX_HS_SLEWRATE 0x0026
#define TX_SYNC_SOURCE 0x0027
#define TX_HS_SYNC_LENGTH 0x0028
#define TX_HS_PREPARE_LENGTH 0x0029
#define TX_LS_PREPARE_LENGTH 0x002A
#define TX_HIBERN8_CONTROL 0x002B
#define TX_LCC_ENABLE 0x002C
#define TX_PWM_BURST_CLOSURE_EXTENSION 0x002D
#define TX_BYPASS_8B10B_ENABLE 0x002E
#define TX_DRIVER_POLARITY 0x002F
#define TX_HS_UNTERMINATED_LINE_DRIVE_ENABLE 0x0030
#define TX_LS_TERMINATED_LINE_DRIVE_ENABLE 0x0031
#define TX_LCC_SEQUENCER 0x0032
#define TX_MIN_ACTIVATETIME 0x0033
#define TX_PWM_G6_G7_SYNC_LENGTH 0x0034
#define TX_REFCLKFREQ 0x00EB
#define TX_CFGCLKFREQVAL 0x00EC
#define CFGEXTRATTR 0x00F0
#define DITHERCTRL2 0x00F1
/*
* M-RX Configuration Attributes
*/
#define RX_MODE 0x00A1
#define RX_HSRATE_SERIES 0x00A2
#define RX_HSGEAR 0x00A3
#define RX_PWMGEAR 0x00A4
#define RX_LS_TERMINATED_ENABLE 0x00A5
#define RX_HS_UNTERMINATED_ENABLE 0x00A6
#define RX_ENTER_HIBERN8 0x00A7
#define RX_BYPASS_8B10B_ENABLE 0x00A8
#define RX_TERMINATION_FORCE_ENABLE 0x0089
#define RX_MIN_ACTIVATETIME_CAPABILITY 0x008F
#define RX_HIBERN8TIME_CAPABILITY 0x0092
#define RX_REFCLKFREQ 0x00EB
#define RX_CFGCLKFREQVAL 0x00EC
#define CFGWIDEINLN 0x00F0
#define CFGRXCDR8 0x00BA
#define ENARXDIRECTCFG4 0x00F2
#define CFGRXOVR8 0x00BD
#define RXDIRECTCTRL2 0x00C7
#define ENARXDIRECTCFG3 0x00F3
#define RXCALCTRL 0x00B4
#define ENARXDIRECTCFG2 0x00F4
#define CFGRXOVR4 0x00E9
#define RXSQCTRL 0x00B5
#define CFGRXOVR6 0x00BF
#define is_mphy_tx_attr(attr) (attr < RX_MODE)
#define RX_MIN_ACTIVATETIME_UNIT_US 100
#define HIBERN8TIME_UNIT_US 100
/*
* Common Block Attributes
*/
#define TX_GLOBALHIBERNATE UNIPRO_CB_OFFSET(0x002B)
#define REFCLKMODE UNIPRO_CB_OFFSET(0x00BF)
#define DIRECTCTRL19 UNIPRO_CB_OFFSET(0x00CD)
#define DIRECTCTRL10 UNIPRO_CB_OFFSET(0x00E6)
#define CDIRECTCTRL6 UNIPRO_CB_OFFSET(0x00EA)
#define RTOBSERVESELECT UNIPRO_CB_OFFSET(0x00F0)
#define CBDIVFACTOR UNIPRO_CB_OFFSET(0x00F1)
#define CBDCOCTRL5 UNIPRO_CB_OFFSET(0x00F3)
#define CBPRGPLL2 UNIPRO_CB_OFFSET(0x00F8)
#define CBPRGTUNING UNIPRO_CB_OFFSET(0x00FB)
#define UNIPRO_CB_OFFSET(x) (0x8000 | x)
/*
* PHY Adpater attributes
*/
#define PA_ACTIVETXDATALANES 0x1560
#define PA_ACTIVERXDATALANES 0x1580
#define PA_TXTRAILINGCLOCKS 0x1564
#define PA_PHY_TYPE 0x1500
#define PA_AVAILTXDATALANES 0x1520
#define PA_AVAILRXDATALANES 0x1540
#define PA_MINRXTRAILINGCLOCKS 0x1543
#define PA_TXPWRSTATUS 0x1567
#define PA_RXPWRSTATUS 0x1582
#define PA_TXFORCECLOCK 0x1562
#define PA_TXPWRMODE 0x1563
#define PA_LEGACYDPHYESCDL 0x1570
#define PA_MAXTXSPEEDFAST 0x1521
#define PA_MAXTXSPEEDSLOW 0x1522
#define PA_MAXRXSPEEDFAST 0x1541
#define PA_MAXRXSPEEDSLOW 0x1542
#define PA_TXLINKSTARTUPHS 0x1544
#define PA_LOCAL_TX_LCC_ENABLE 0x155E
#define PA_TXSPEEDFAST 0x1565
#define PA_TXSPEEDSLOW 0x1566
#define PA_REMOTEVERINFO 0x15A0
#define PA_TXGEAR 0x1568
#define PA_TXTERMINATION 0x1569
#define PA_HSSERIES 0x156A
#define PA_PWRMODE 0x1571
#define PA_RXGEAR 0x1583
#define PA_RXTERMINATION 0x1584
#define PA_MAXRXPWMGEAR 0x1586
#define PA_MAXRXHSGEAR 0x1587
#define PA_RXHSUNTERMCAP 0x15A5
#define PA_RXLSTERMCAP 0x15A6
#define PA_GRANULARITY 0x15AA
#define PA_PACPREQTIMEOUT 0x1590
#define PA_PACPREQEOBTIMEOUT 0x1591
#define PA_HIBERN8TIME 0x15A7
#define PA_LOCALVERINFO 0x15A9
#define PA_TACTIVATE 0x15A8
#define PA_PACPFRAMECOUNT 0x15C0
#define PA_PACPERRORCOUNT 0x15C1
#define PA_PHYTESTCONTROL 0x15C2
#define PA_PWRMODEUSERDATA0 0x15B0
#define PA_PWRMODEUSERDATA1 0x15B1
#define PA_PWRMODEUSERDATA2 0x15B2
#define PA_PWRMODEUSERDATA3 0x15B3
#define PA_PWRMODEUSERDATA4 0x15B4
#define PA_PWRMODEUSERDATA5 0x15B5
#define PA_PWRMODEUSERDATA6 0x15B6
#define PA_PWRMODEUSERDATA7 0x15B7
#define PA_PWRMODEUSERDATA8 0x15B8
#define PA_PWRMODEUSERDATA9 0x15B9
#define PA_PWRMODEUSERDATA10 0x15BA
#define PA_PWRMODEUSERDATA11 0x15BB
#define PA_CONNECTEDTXDATALANES 0x1561
#define PA_CONNECTEDRXDATALANES 0x1581
#define PA_LOGICALLANEMAP 0x15A1
#define PA_SLEEPNOCONFIGTIME 0x15A2
#define PA_STALLNOCONFIGTIME 0x15A3
#define PA_SAVECONFIGTIME 0x15A4
#define PA_TACTIVATE_TIME_UNIT_US 10
#define PA_HIBERN8_TIME_UNIT_US 100
/*Other attributes*/
#define VS_MPHYCFGUPDT 0xD085
#define VS_DEBUGOMC 0xD09E
#define VS_POWERSTATE 0xD083
#define PA_GRANULARITY_MIN_VAL 1
#define PA_GRANULARITY_MAX_VAL 6
/* PHY Adapter Protocol Constants */
#define PA_MAXDATALANES 4
/* PA power modes */
enum {
FAST_MODE = 1,
SLOW_MODE = 2,
FASTAUTO_MODE = 4,
SLOWAUTO_MODE = 5,
UNCHANGED = 7,
};
/* PA TX/RX Frequency Series */
enum {
PA_HS_MODE_A = 1,
PA_HS_MODE_B = 2,
};
enum ufs_pwm_gear_tag {
UFS_PWM_DONT_CHANGE, /* Don't change Gear */
UFS_PWM_G1, /* PWM Gear 1 (default for reset) */
UFS_PWM_G2, /* PWM Gear 2 */
UFS_PWM_G3, /* PWM Gear 3 */
UFS_PWM_G4, /* PWM Gear 4 */
UFS_PWM_G5, /* PWM Gear 5 */
UFS_PWM_G6, /* PWM Gear 6 */
UFS_PWM_G7, /* PWM Gear 7 */
};
enum ufs_hs_gear_tag {
UFS_HS_DONT_CHANGE, /* Don't change Gear */
UFS_HS_G1, /* HS Gear 1 (default for reset) */
UFS_HS_G2, /* HS Gear 2 */
UFS_HS_G3, /* HS Gear 3 */
};
enum ufs_unipro_ver {
UFS_UNIPRO_VER_RESERVED = 0,
UFS_UNIPRO_VER_1_40 = 1, /* UniPro version 1.40 */
UFS_UNIPRO_VER_1_41 = 2, /* UniPro version 1.41 */
UFS_UNIPRO_VER_1_6 = 3, /* UniPro version 1.6 */
UFS_UNIPRO_VER_MAX = 4, /* UniPro unsupported version */
/* UniPro version field mask in PA_LOCALVERINFO */
UFS_UNIPRO_VER_MASK = 0xF,
};
/*
* Data Link Layer Attributes
*/
#define DL_TC0TXFCTHRESHOLD 0x2040
#define DL_FC0PROTTIMEOUTVAL 0x2041
#define DL_TC0REPLAYTIMEOUTVAL 0x2042
#define DL_AFC0REQTIMEOUTVAL 0x2043
#define DL_AFC0CREDITTHRESHOLD 0x2044
#define DL_TC0OUTACKTHRESHOLD 0x2045
#define DL_TC1TXFCTHRESHOLD 0x2060
#define DL_FC1PROTTIMEOUTVAL 0x2061
#define DL_TC1REPLAYTIMEOUTVAL 0x2062
#define DL_AFC1REQTIMEOUTVAL 0x2063
#define DL_AFC1CREDITTHRESHOLD 0x2064
#define DL_TC1OUTACKTHRESHOLD 0x2065
#define DL_TXPREEMPTIONCAP 0x2000
#define DL_TC0TXMAXSDUSIZE 0x2001
#define DL_TC0RXINITCREDITVAL 0x2002
#define DL_TC0TXBUFFERSIZE 0x2005
#define DL_PEERTC0PRESENT 0x2046
#define DL_PEERTC0RXINITCREVAL 0x2047
#define DL_TC1TXMAXSDUSIZE 0x2003
#define DL_TC1RXINITCREDITVAL 0x2004
#define DL_TC1TXBUFFERSIZE 0x2006
#define DL_PEERTC1PRESENT 0x2066
#define DL_PEERTC1RXINITCREVAL 0x2067
/*
* Network Layer Attributes
*/
#define N_DEVICEID 0x3000
#define N_DEVICEID_VALID 0x3001
#define N_TC0TXMAXSDUSIZE 0x3020
#define N_TC1TXMAXSDUSIZE 0x3021
/*
* Transport Layer Attributes
*/
#define T_NUMCPORTS 0x4000
#define T_NUMTESTFEATURES 0x4001
#define T_CONNECTIONSTATE 0x4020
#define T_PEERDEVICEID 0x4021
#define T_PEERCPORTID 0x4022
#define T_TRAFFICCLASS 0x4023
#define T_PROTOCOLID 0x4024
#define T_CPORTFLAGS 0x4025
#define T_TXTOKENVALUE 0x4026
#define T_RXTOKENVALUE 0x4027
#define T_LOCALBUFFERSPACE 0x4028
#define T_PEERBUFFERSPACE 0x4029
#define T_CREDITSTOSEND 0x402A
#define T_CPORTMODE 0x402B
#define T_TC0TXMAXSDUSIZE 0x4060
#define T_TC1TXMAXSDUSIZE 0x4061
#ifdef FALSE
#undef FALSE
#endif
#ifdef TRUE
#undef TRUE
#endif
/* Boolean attribute values */
enum {
FALSE = 0,
TRUE,
};
#endif /* _UNIPRO_H_ */

View File

@ -102,6 +102,7 @@ enum uclass_id {
UCLASS_THERMAL, /* Thermal sensor */
UCLASS_TIMER, /* Timer device */
UCLASS_TPM, /* Trusted Platform Module TIS interface */
UCLASS_UFS, /* Universal Flash Storage */
UCLASS_USB, /* USB bus */
UCLASS_USB_DEV_GENERIC, /* USB generic device */
UCLASS_USB_HUB, /* USB hub */

29
include/ufs.h Normal file
View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef _UFS_H
#define _UFS_H
/**
* ufs_probe() - initialize all devices in the UFS uclass
*
* @return 0 if Ok, -ve on error
*/
int ufs_probe(void);
/**
* ufs_probe_dev() - initialize a particular device in the UFS uclass
*
* @index: index in the uclass sequence
*
* @return 0 if successfully probed, -ve on error
*/
int ufs_probe_dev(int index);
/*
* ufs_scsi_bind() - Create a new scsi device as a child of the UFS device and
* bind it to the ufs_scsi driver
* @ufs_dev: UFS device
* @scsi_devp: Pointer to scsi device
*
* @return 0 if Ok, -ve on error
*/
int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp);
#endif