summaryrefslogtreecommitdiff
path: root/components/drivers/include
diff options
context:
space:
mode:
authorGuEe-GUI <[email protected]>2026-03-29 21:57:54 +0800
committerRbb666 <[email protected]>2026-05-04 18:41:16 +0800
commitea13820c2c1f22d3f22b39142c2ee3e0f5172efa (patch)
tree88d620f250e9510e3075dc689ec372c5d16d8f54 /components/drivers/include
parentc1a43bc0deb17e6579d838dd7400618eb13d618c (diff)
[dm][ufs] support Universal Flash Storage (UFS)
Support UFS over PCI, too. Signed-off-by: GuEe-GUI <[email protected]>
Diffstat (limited to 'components/drivers/include')
-rwxr-xr-xcomponents/drivers/include/drivers/ufs.h662
-rw-r--r--components/drivers/include/rtdevice.h4
2 files changed, 666 insertions, 0 deletions
diff --git a/components/drivers/include/drivers/ufs.h b/components/drivers/include/drivers/ufs.h
new file mode 100755
index 0000000000..c38de94e4a
--- /dev/null
+++ b/components/drivers/include/drivers/ufs.h
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#ifndef __UFS_H__
+#define __UFS_H__
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <drivers/blk.h>
+#include <drivers/misc.h>
+#include <drivers/scsi.h>
+#include <drivers/byteorder.h>
+
+#define __BIT_FIELD(v, h, l) ((v & RT_GENMASK(h, l)) >> l)
+
+/* Host Capabilities */
+#define RT_UFS_REG_CAP 0x00 /* Host Controller Capabiities */
+#define RT_UFS_REG_CAP_NUTRS(v) __BIT_FIELD(v, 4, 0) /* Number of UTP Transfer Request Slots */
+#define RT_UFS_REG_CAP_NORTT(v) __BIT_FIELD(v, 15, 8) /* Number of outstanding READY TO TRANSFER requests supported */
+#define RT_UFS_REG_CAP_NUTMRS(v) __BIT_FIELD(v, 18, 16) /* Number of UTP Task Management Request Slots */
+#define RT_UFS_REG_CAP_AUTOH8 RT_BIT(23) /* Auto-Hibernation Support */
+#define RT_UFS_REG_CAP_64AS RT_BIT(24) /* 64-bit addressing supported */
+#define RT_UFS_REG_CAP_OODDS RT_BIT(25) /* Out of order data delivery supported */
+#define RT_UFS_REG_CAP_UICDMETMS RT_BIT(26) /* UIC DME_TEST_MODE command supported */
+#define RT_UFS_REG_CAP_UME RT_BIT(27) /* Reserved for Unified Memory Extension */
+#define RT_UFS_REG_VER 0x08 /* UFS Version */
+#define RT_UFS_REG_VER_VS(v) __BIT_FIELD(v, 03, 0) /* Version Suffix (VS) */
+#define RT_UFS_REG_VER_MNR(v) __BIT_FIELD(v, 07, 4) /* Minor Version Number (MNR) */
+#define RT_UFS_REG_VER_MJR(v) __BIT_FIELD(v, 15, 8) /* Major Version Number (MJR) */
+#define RT_UFS_REG_HCPID 0x10 /* Host Controller Identification Descriptor – Product ID */
+#define RT_UFS_REG_HCMID 0x14 /* Host Controller Identification Descriptor – Manufacturer ID */
+#define RT_UFS_REG_HCMID_MIC(v) __BIT_FIELD(v, 7, 0) /* Manufacturer Identification Code */
+#define RT_UFS_REG_HCMID_BI(v) __BIT_FIELD(v, 15, 8) /* Bank Index */
+#define RT_UFS_REG_AHIT 0x18 /* Auto-Hibernate Idle Timer */
+#define RT_UFS_REG_AHIT_AH8ITV(v) __BIT_FIELD(v, 9, 0) /* Auto-Hibern8 Idle Timer Value */
+#define RT_UFS_REG_AHIT_TS(v) __BIT_FIELD(v, 12, 10) /* Timer scale */
+/* Operation and Runtime */
+#define RT_UFS_REG_IS 0x20 /* Interrupt Status */
+#define RT_UFS_REG_IS_UTRCS RT_BIT(0) /* UTP Transfer Request Completion Status */
+#define RT_UFS_REG_IS_UDEPRI RT_BIT(1) /* UIC DME_ENDPOINTRESET Indication */
+#define RT_UFS_REG_IS_UE RT_BIT(2) /* UIC Error */
+#define RT_UFS_REG_IS_UTMS RT_BIT(3) /* UIC Test Mode Status */
+#define RT_UFS_REG_IS_UPMS RT_BIT(4) /* UIC Power Mode Status */
+#define RT_UFS_REG_IS_UHXS RT_BIT(5) /* UIC Hibernate Exit Status */
+#define RT_UFS_REG_IS_UHES RT_BIT(6) /* UIC Hibernate Enter Status */
+#define RT_UFS_REG_IS_ULLS RT_BIT(7) /* UIC Link Lost Status */
+#define RT_UFS_REG_IS_ULSS RT_BIT(8) /* UIC Link Startup Status */
+#define RT_UFS_REG_IS_UTMRCS RT_BIT(9) /* UTP Task Management Request Completion Status */
+#define RT_UFS_REG_IS_UCCS RT_BIT(10) /* UIC Command Completion Status */
+#define RT_UFS_REG_IS_DFES RT_BIT(11) /* Device Fatal Error Status */
+#define RT_UFS_REG_IS_UTPES RT_BIT(12) /* UTP Error Status */
+#define RT_UFS_REG_IS_HCFES RT_BIT(16) /* Host Controller Fatal Error Status */
+#define RT_UFS_REG_IS_SBFES RT_BIT(17) /* System Bus Fatal Error Status */
+#define RT_UFS_REG_IE 0x24 /* Interrupt Enable */
+#define RT_UFS_REG_IE_UTRCE RT_BIT(0) /* UTP Transfer Request Completion Enable */
+#define RT_UFS_REG_IE_UDEPRIE RT_BIT(1) /* UIC DME_ENDPOINTRESET */
+#define RT_UFS_REG_IE_UEE RT_BIT(2) /* UIC Error Enable */
+#define RT_UFS_REG_IE_UTMSE RT_BIT(3) /* UIC Test Mode Status Enable */
+#define RT_UFS_REG_IE_UPMSE RT_BIT(4) /* UIC Power Mode Status Enable */
+#define RT_UFS_REG_IE_UHXSE RT_BIT(5) /* UIC Hibernate Exit Status Enable */
+#define RT_UFS_REG_IE_UHESE RT_BIT(6) /* UIC Hibernate Enter Status Enable */
+#define RT_UFS_REG_IE_ULLSE RT_BIT(7) /* UIC Link Lost Status Enable */
+#define RT_UFS_REG_IE_ULSSE RT_BIT(8) /* UIC Link Startup Status Enable */
+#define RT_UFS_REG_IE_UTMRCE RT_BIT(9) /* UTP Task Management Request Completion Enable */
+#define RT_UFS_REG_IE_UCCE RT_BIT(10) /* UIC COMMAND Completion Enable */
+#define RT_UFS_REG_IE_DFEE RT_BIT(11) /* Device Fatal Error Enable */
+#define RT_UFS_REG_IE_UTPEE RT_BIT(12) /* UTP Error Enable */
+#define RT_UFS_REG_IE_HCFEE RT_BIT(16) /* Host Controller Fatal Error Enable */
+#define RT_UFS_REG_IE_SBFEE RT_BIT(17) /* System Bus Fatal Error Enable */
+#define RT_UFS_REG_HCS 0x30 /* Host Controller Status */
+#define RT_UFS_REG_HCS_DP RT_BIT(0) /* Device Present */
+#define RT_UFS_REG_HCS_UTRLRDY RT_BIT(1) /* UTP Transfer Request List Ready */
+#define RT_UFS_REG_HCS_UTMRLRDY RT_BIT(2) /* UTP Task Management Request List Ready */
+#define RT_UFS_REG_HCS_UCRDY RT_BIT(3) /* UIC COMMAND Ready */
+#define RT_UFS_REG_HCS_UPMCRS(v) __BIT_FIELD(v, 10, 8) /* UIC Power Mode Change Request Status */
+#define RT_UFS_REG_HCS_UTPEC(v) __BIT_FIELD(v, 15, 12) /* UTP Error Code */
+#define RT_UFS_REG_HCS_TTAGUTPE(v) __BIT_FIELD(v, 23, 16) /* Task Tag of UTP error */
+#define RT_UFS_REG_HCS_TLUNUTPE(v) __BIT_FIELD(v, 31, 24) /* Target LUN of UTP error */
+#define RT_UFS_REG_HCE 0x34 /* Host Controller Enable */
+#define RT_UFS_REG_UECPA 0x38 /* Host UIC Error Code PHY Adapter Layer */
+#define RT_UFS_REG_UECPA_EC(v) __BIT_FIELD(v, 4, 0) /* UIC PHY Adapter Layer Error Code */
+#define RT_UFS_REG_UECPA_ERR RT_BIT(31) /* UIC PHY AdapterA Layer Error */
+#define RT_UFS_REG_UECDL 0x3c /* Host UIC Error Code Data Link Layer */
+#define RT_UFS_REG_UECDL_EC(v) __BIT_FIELD(v, 14, 0) /* UIC Data Link Layer Error Code */
+#define RT_UFS_REG_UECDL_ERR RT_BIT(31) /* UIC Data Link Layer Error */
+#define RT_UFS_REG_UECN 0x40 /* Host UIC Error Code Network Layer */
+#define RT_UFS_REG_UECN_EC(v) __BIT_FIELD(v, 2, 0) /* UIC Network Layer Error Code */
+#define RT_UFS_REG_UECN_ERR RT_BIT(31) /* UIC Network Layer Error */
+#define RT_UFS_REG_UECT 0x44 /* Host UIC Error Code Transport Layer */
+#define RT_UFS_REG_UECT_EC(v) __BIT_FIELD(v, 6, 0) /* UIC Transport Layer Error Code */
+#define RT_UFS_REG_UECT_ERR RT_BIT(31) /* UIC Transport Layer Error */
+#define RT_UFS_REG_UECDME 0x48 /* Host UIC Error Code DME */
+#define RT_UFS_REG_UECDME_EC(v) __BIT_FIELD(v, 0, 0) /* UIC DME Error Code */
+#define RT_UFS_REG_UECDME_ERR RT_BIT(31) /* UIC DME Error */
+#define RT_UFS_REG_UTRIACR 0x4c /* UTP Transfer Request Interrupt Aggregation Control Register */
+#define RT_UFS_REG_UTRIACR_IAEN RT_BIT(31) /* Interrupt Aggregation Enable/Disable */
+#define RT_UFS_REG_UTRIACR_IAPWEN RT_BIT(24) /* Interrupt aggregation parameter write enable */
+#define RT_UFS_REG_UTRIACR_IASB RT_BIT(20) /* Interrupt aggregation status bit */
+#define RT_UFS_REG_UTRIACR_CTR RT_BIT(16) /* Counter and Timer Reset */
+#define RT_UFS_REG_UTRIACR_IACTH(v) __BIT_FIELD(v, 12, 8) /* Interrupt aggregation counter threshold */
+#define RT_UFS_REG_UTRIACR_IATOVAL(v) __BIT_FIELD(v, 7, 0) /* Interrupt aggregation timeout (40us units) */
+/* UTRIACR compose */
+#define RT_UFS_UTRIACR_TIMEOUT_MASK RT_GENMASK(7, 0)
+#define RT_UFS_UTRIACR_COUNTER_THLD_MASK RT_GENMASK(12, 8)
+#define RT_UFS_UTRIACR_CTR RT_BIT(16)
+#define RT_UFS_UTRIACR_IASB RT_BIT(20)
+#define RT_UFS_UTRIACR_IAPWEN RT_BIT(24)
+#define RT_UFS_UTRIACR_IAEN RT_BIT(31)
+#define RT_UFS_UTRIACR_COUNTER_THLD(c) ((((rt_uint32_t)(c)) & 0x1fu) << 8)
+#define RT_UFS_UTRIACR_TIMEOUT(t) (((rt_uint32_t)(t)) & 0xffu)
+#define RT_UFS_UTRIACR_ENABLE_PARAMS(cnt, to) (RT_UFS_UTRIACR_IAEN | RT_UFS_UTRIACR_IAPWEN | \
+ RT_UFS_UTRIACR_COUNTER_THLD(cnt) | RT_UFS_UTRIACR_TIMEOUT(to))
+#define RT_UFS_UTRIACR_RESET (RT_UFS_UTRIACR_IAEN | RT_UFS_UTRIACR_CTR)
+/* UTP Transfer */
+#define RT_UFS_REG_UTRLBA 0x50 /* UTP Transfer Request List Base Address */
+#define RT_UFS_REG_UTRLBA_MASK(v) __BIT_FIELD(v, 31, 10)
+#define RT_UFS_REG_UTRLBAU 0x54 /* UTP Transfer Request List Base Address Upper 32-Bits */
+#define RT_UFS_REG_UTRLBAU_MASK(v) __BIT_FIELD(v, 31, 0)
+#define RT_UFS_REG_UTRLDBR 0x58 /* UTP Transfer Request List Door Bell Register */
+#define RT_UFS_REG_UTRLCLR 0x5c /* UTP Transfer Request List CLear Register */
+#define RT_UFS_REG_UTRLRSR 0x60 /* UTP Transfer Request Run-Stop Register */
+/* UTP Task Managemeng */
+#define RT_UFS_REG_UTMRLBA 0x70 /* UTP Task Management Request List Base Address */
+#define RT_UFS_REG_UTMRLBA_MASK(v) __BIT_FIELD(v, 31, 10)
+#define RT_UFS_REG_UTMRLBAU 0x74 /* UTP Task Management Request List Base Address Upper 32-Bits */
+#define RT_UFS_REG_UTMRLBAU_MASK(v) __BIT_FIELD(v, 31, 0)
+#define RT_UFS_REG_UTMRLDBR 0x78 /* UTP Task Management Request List Door Bell Register */
+#define RT_UFS_REG_UTMRLCLR 0x7c /* UTP Task Management Request List CLear Register */
+#define RT_UFS_REG_UTMRLRSR 0x80 /* UTP Task Management Run-Stop Register */
+/* UIC Command */
+#define RT_UFS_REG_UICCMD 0x90 /* UIC Command Register */
+#define RT_UFS_REG_UICCMD_CMDOP(v) __BIT_FIELD(v, 7, 0) /* Command Opcode */
+#define RT_UFS_REG_UCMDARG1 0x94 /* UIC Command Argument 1 */
+#define RT_UFS_REG_UCMDARG2 0x98 /* UIC Command Argument 2 */
+#define RT_UFS_REG_UCMDARG3 0x9c /* UIC Command Argument 3 */
+/* UMA */
+#define RT_UFS_REG_UMA_EXT 0xb0 /* Reserved for Unified Memory Extension */
+/* Vendor Specific */
+#define RT_UFS_REG_VS 0xc0 /* Vendor Specific Registers */
+
+/* UTP Error Code */
+enum
+{
+ RT_UFS_UTPEC_ERR_INV_TYPE = 1,
+};
+
+/* UIC Power Mode Change Request Status */
+enum
+{
+ RT_UFS_UPMCRS_PWR_OK = 0x0,
+ RT_UFS_UPMCRS_PWR_LOCAL = 0x1,
+ RT_UFS_UPMCRS_PWR_REMOTE = 0x2,
+ RT_UFS_UPMCRS_PWR_BUSY = 0x3,
+ RT_UFS_UPMCRS_PWR_ERROR_CAP = 0x4,
+ RT_UFS_UPMCRS_PWR_FATAL_ERROR = 0x5,
+};
+
+/* UIC PHY Adapter Layer Error Code */
+enum
+{
+ RT_UFS_UECPA_EC_LANE0 = RT_BIT(0),
+ RT_UFS_UECPA_EC_LANE1 = RT_BIT(1),
+ RT_UFS_UECPA_EC_LANE2 = RT_BIT(2),
+ RT_UFS_UECPA_EC_LANE3 = RT_BIT(3),
+ RT_UFS_UECPA_EC_GENERIC = RT_BIT(4),
+};
+
+/* UIC Data Link Layer Error Code */
+enum
+{
+ RT_UFS_UECDL_EC_NAC_RECEIVED = RT_BIT(0),
+ RT_UFS_UECDL_EC_TCx_REPLAY_TIMER_EXPIRED = RT_BIT(1),
+ RT_UFS_UECDL_EC_AFCx_REQUEST_TIMER_EXPIRED = RT_BIT(2),
+ RT_UFS_UECDL_EC_FCx_PROTECTION_TIMER_EXPIRED = RT_BIT(3),
+ RT_UFS_UECDL_EC_CRC_ERROR = RT_BIT(4),
+ RT_UFS_UECDL_EC_RX_BUFFER_OVERFLOW = RT_BIT(5),
+ RT_UFS_UECDL_EC_MAX_FRAME_LENGTH_EXCEEDED = RT_BIT(6),
+ RT_UFS_UECDL_EC_WRONG_SEQUENCE_NUMBER = RT_BIT(7),
+ RT_UFS_UECDL_EC_AFC_FRAME_SYNTAX_ERROR = RT_BIT(8),
+ RT_UFS_UECDL_EC_NAC_FRAME_SYNTAX_ERROR = RT_BIT(9),
+ RT_UFS_UECDL_EC_EOF_SYNTAX_ERROR = RT_BIT(10),
+ RT_UFS_UECDL_EC_FRAME_SYNTAX_ERROR = RT_BIT(11),
+ RT_UFS_UECDL_EC_BAD_CTRL_SYMBOL_TYPE = RT_BIT(12),
+ RT_UFS_UECDL_EC_PA_INIT_ERROR = RT_BIT(13),
+ RT_UFS_UECDL_EC_PA_ERROR_IND_RECEIVED = RT_BIT(14),
+};
+
+/* UIC Network Layer Error Code */
+enum
+{
+ RT_UFS_UECN_EC_UNSUPPORTED_HEADER_TYPE = RT_BIT(0),
+ RT_UFS_UECN_EC_BAD_DEVICEID_ENC = RT_BIT(1),
+ RT_UFS_UECN_EC_LHDR_TRAP_PACKET_DROPPING = RT_BIT(2),
+};
+
+/* UIC Transport Layer Error Code */
+enum
+{
+ RT_UFS_UECT_EC_UNSUPPORTED_HEADER_TYPE = RT_BIT(0),
+ RT_UFS_UECT_EC_UNKNOWN_CPORTID = RT_BIT(1),
+ RT_UFS_UECT_EC_NO_CONNECTION_RX = RT_BIT(2),
+ RT_UFS_UECT_EC_CONTROLLED_SEGMENT_DROPPING = RT_BIT(3),
+ RT_UFS_UECT_EC_BAD_TC = RT_BIT(4),
+ RT_UFS_UECT_EC_E2E_CREDIT_OVERFLOW = RT_BIT(5),
+ RT_UFS_UECT_EC_SAFETY_VALVE_DROPPING = RT_BIT(6),
+};
+
+/* UIC DME Error Code */
+enum
+{
+ RT_UFS_UECDME_EC_GENERIC = RT_BIT(0),
+};
+
+/* UIC Command Opcode */
+enum
+{
+ /* Configuration */
+ RT_UFS_CMDOP_DME_GET = 0x1,
+ RT_UFS_CMDOP_DME_SET = 0x2,
+ RT_UFS_CMDOP_DME_PEER_GET = 0x3,
+ RT_UFS_CMDOP_DME_PEER_SET = 0x4,
+ /* Control */
+ RT_UFS_CMDOP_DME_POWERON = 0x10,
+ RT_UFS_CMDOP_DME_POWEROFF = 0x11,
+ RT_UFS_CMDOP_DME_ENABLE = 0x12,
+ RT_UFS_CMDOP_DME_RESET = 0x14,
+ RT_UFS_CMDOP_DME_ENDPOINTRESET = 0x15,
+ RT_UFS_CMDOP_DME_LINKSTARTUP = 0x16,
+ RT_UFS_CMDOP_DME_HIBERNATE_ENTER = 0x17,
+ RT_UFS_CMDOP_DME_HIBERNATE_EXIT = 0x18,
+ RT_UFS_CMDOP_DME_TEST_MODE = 0x1a,
+};
+
+/* UIC Config result code / Generic error code */
+enum
+{
+ RT_UFS_CMDRES_SUCCESS = 0x0,
+ RT_UFS_CMDRES_INVALID_MIB_ATTRIBUTE = 0x1,
+ RT_UFS_CMDRES_INVALID_MIB_ATTRIBUTE_VALUE = 0x2,
+ RT_UFS_CMDRES_READ_ONLY_MIB_ATTRIBUTE = 0x3,
+ RT_UFS_CMDRES_WRITE_ONLY_MIB_ATTRIBUTE = 0x4,
+ RT_UFS_CMDRES_BAD_INDEX = 0x5,
+ RT_UFS_CMDRES_LOCKED_MIB_ATTRIBUTE = 0x6,
+ RT_UFS_CMDRES_BAD_TEST_FEATURE_INDEX = 0x7,
+ RT_UFS_CMDRES_PEER_COMMUNICATION_FAILURE = 0x8,
+ RT_UFS_CMDRES_BUSY = 0x9,
+ RT_UFS_CMDRES_DME_FAILURE = 0xa,
+ RT_UFS_CMDRES_MASK = 0xff,
+};
+
+/*
+ * UIC DME attribute encoding (JEDEC UFS / UniPro PA)
+ */
+#define RT_UFS_UIC_ARG_MIB_SEL(attr, sel) ((((rt_uint32_t)(attr) & 0xffffU) << 16) | ((rt_uint32_t)(sel) & 0xffffU))
+#define RT_UFS_UIC_ARG_MIB(attr) RT_UFS_UIC_ARG_MIB_SEL(attr, 0)
+
+/* PHY Adapter — subset used for power / link configuration */
+#define RT_UFS_PA_RXGEAR 0x1583
+#define RT_UFS_PA_TXGEAR 0x1568
+#define RT_UFS_PA_ACTIVERXDATALANES 0x1580
+#define RT_UFS_PA_ACTIVETXDATALANES 0x1560
+#define RT_UFS_PA_RXTERMINATION 0x1584
+#define RT_UFS_PA_TXTERMINATION 0x1569
+#define RT_UFS_PA_HSSERIES 0x156a
+#define RT_UFS_PA_PWRMODE 0x1571
+#define RT_UFS_PA_PWRMODEUSERDATA0 0x15b0
+#define RT_UFS_PA_PWRMODEUSERDATA1 0x15b1
+#define RT_UFS_PA_PWRMODEUSERDATA2 0x15b2
+#define RT_UFS_PA_PWRMODEUSERDATA3 0x15b3
+#define RT_UFS_PA_PWRMODEUSERDATA4 0x15b4
+#define RT_UFS_PA_PWRMODEUSERDATA5 0x15b5
+#define RT_UFS_DME_LOCAL_FC0_PROT_TO 0xd041
+#define RT_UFS_DME_LOCAL_TC0_REPLAY_TO 0xd042
+#define RT_UFS_DME_LOCAL_AFC0_REQ_TO 0xd043
+
+#define RT_UFS_DL_FC0_PROT_TO_DEFAULT 8191U
+#define RT_UFS_DL_TC0_REPLAY_TO_DEFAULT 65535U
+#define RT_UFS_DL_AFC0_REQ_TO_DEFAULT 32767U
+#define RT_UFS_DL_FC1_PROT_TO_DEFAULT 8191U
+#define RT_UFS_DL_TC1_REPLAY_TO_DEFAULT 65535U
+#define RT_UFS_DL_AFC1_REQ_TO_DEFAULT 32767U
+
+enum rt_ufs_pa_pwr_mode
+{
+ RT_UFS_PA_FAST_MODE = 1,
+ RT_UFS_PA_SLOW_MODE = 2,
+ RT_UFS_PA_FASTAUTO_MODE = 4,
+ RT_UFS_PA_SLOWAUTO_MODE = 5,
+ RT_UFS_PA_UNCHANGED_MODE = 7,
+};
+
+enum rt_ufs_pa_hs_rate
+{
+ RT_UFS_PA_HS_MODE_A = 1,
+ RT_UFS_PA_HS_MODE_B = 2,
+};
+
+/* Auto-Hibernate Idle Timer (AHIT) — REG 0x18 */
+#define RT_UFS_AHIT_TIMER_MASK RT_GENMASK(9, 0)
+#define RT_UFS_AHIT_SCALE_MASK RT_GENMASK(12, 10)
+
+rt_inline rt_uint32_t rt_ufs_ahit_encode(rt_uint16_t timer, rt_uint8_t scale)
+{
+ return ((rt_uint32_t)timer & RT_UFS_AHIT_TIMER_MASK) | (((rt_uint32_t)scale << 10) & RT_UFS_AHIT_SCALE_MASK);
+}
+
+/* 150 * 10^3 us idle before auto-Hibernate8 */
+#define RT_UFS_AHIT_DEFAULT rt_ufs_ahit_encode(150, 3)
+
+/*
+ * UTP / UPIU (refer to JEDEC UFS & UFSHCI)
+ */
+#define RT_UFS_CDB_SIZE 16
+#define RT_UFS_ALIGNED_UPIU_SIZE 512
+#define RT_UFS_SENSE_SIZE 18
+
+/* UTP Transfer Request Command Type */
+#define RT_UTP_CMD_TYPE_SCSI 0x0
+#define RT_UTP_CMD_TYPE_UFS_STORAGE 0x1
+#define RT_UTP_CMD_TYPE_DEV_MANAGE 0x2
+
+/* UTP Data Direction */
+#define RT_UTP_NO_DATA_TRANSFER 0
+#define RT_UTP_HOST_TO_DEVICE 1
+#define RT_UTP_DEVICE_TO_HOST 2
+
+/* Overall Command Status (OCS) in UTRD */
+enum rt_ufs_ocs
+{
+ RT_UFS_OCS_SUCCESS = 0x0,
+ RT_UFS_OCS_INVALID_CMD_TABLE_ATTR = 0x1,
+ RT_UFS_OCS_INVALID_PRDT_ATTR = 0x2,
+ RT_UFS_OCS_MISMATCH_DATA_BUF_SIZE = 0x3,
+ RT_UFS_OCS_MISMATCH_RESP_UPIU_SIZE = 0x4,
+ RT_UFS_OCS_PEER_COMM_FAILURE = 0x5,
+ RT_UFS_OCS_ABORTED = 0x6,
+ RT_UFS_OCS_FATAL_ERROR = 0x7,
+ RT_UFS_OCS_DEVICE_FATAL_ERROR = 0x8,
+ RT_UFS_OCS_INVALID_COMMAND_STATUS = 0xf,
+};
+
+/* UPIU Transaction Codes (Initiator to Target) */
+#define RT_UPIU_TRANSACTION_NOP_OUT 0x00
+#define RT_UPIU_TRANSACTION_COMMAND 0x01
+#define RT_UPIU_TRANSACTION_DATA_OUT 0x02
+#define RT_UPIU_TRANSACTION_TASK_REQ 0x04
+#define RT_UPIU_TRANSACTION_QUERY_REQ 0x16
+
+/* UPIU Transaction Codes (Target to Initiator) */
+#define RT_UPIU_TRANSACTION_NOP_IN 0x20
+#define RT_UPIU_TRANSACTION_RESPONSE 0x21
+#define RT_UPIU_TRANSACTION_DATA_IN 0x22
+#define RT_UPIU_TRANSACTION_TASK_RSP 0x24
+#define RT_UPIU_TRANSACTION_QUERY_RSP 0x36
+
+/* UPIU Command Set Type */
+#define RT_UPIU_COMMAND_SET_TYPE_SCSI 0x0
+
+/* UPIU Command flags */
+#define RT_UPIU_CMD_FLAGS_NONE 0x00
+#define RT_UPIU_CMD_FLAGS_WRITE 0x20
+#define RT_UPIU_CMD_FLAGS_READ 0x40
+
+/* PRDT: max single entry size 256KB, granularity 4 bytes */
+#define RT_UFS_PRDT_BYTE_COUNT_MAX (256 * 1024)
+
+/* UPIU header - 12 bytes, big-endian */
+rt_packed(struct rt_utp_upiu_header
+{
+ rt_uint8_t transaction_code;
+ rt_uint8_t flags;
+ rt_uint8_t lun;
+ rt_uint8_t task_tag;
+ rt_uint8_t command_set_type; /* 4:0, iid 7:5 in same byte on LE */
+ rt_uint8_t query_function; /* or tm_function */
+ rt_uint8_t response;
+ rt_uint8_t status;
+ rt_uint8_t ehs_length;
+ rt_uint8_t device_information;
+ rt_be16_t data_segment_length;
+});
+
+/* Command UPIU - SCSI CDB */
+rt_packed(struct rt_utp_upiu_cmd
+{
+ rt_be32_t exp_data_transfer_len;
+ rt_uint8_t cdb[RT_UFS_CDB_SIZE];
+});
+
+/* Request UPIU - command type */
+rt_packed(struct rt_utp_upiu_req
+{
+ struct rt_utp_upiu_header header;
+ struct rt_utp_upiu_cmd sc;
+});
+
+/* Response UPIU - SCSI response (cmd_rsp) */
+rt_packed(struct rt_utp_cmd_rsp
+{
+ rt_be32_t residual_transfer_count;
+ rt_be32_t reserved[4];
+ rt_be16_t sense_data_len;
+ rt_uint8_t sense_data[RT_UFS_SENSE_SIZE];
+});
+
+rt_packed(struct rt_utp_upiu_rsp
+{
+ struct rt_utp_upiu_header header;
+ struct rt_utp_cmd_rsp sr;
+});
+
+/* Physical Region Descriptor Table entry (LE, used by controller) */
+rt_packed(struct rt_ufs_sg_entry
+{
+ rt_uint64_t addr; /* LE in memory for UFSHCI */
+ rt_uint32_t reserved;
+ rt_uint32_t size; /* LE */
+});
+
+/* Request Descriptor Header - common to UTRD/UTMRD (4DW) */
+rt_packed(struct rt_ufs_request_desc_header
+{
+ rt_uint32_t dword_0;
+ rt_uint32_t dword_1;
+ rt_uint32_t dword_2;
+ rt_uint32_t dword_3;
+});
+
+/* UTP Transfer Request Descriptor bits (dword_0) */
+#define RT_UFS_UPIU_COMMAND_TYPE_OFFSET 28
+#define RT_UFS_UTP_REQ_DESC_INT_CMD 0x01000000
+
+/* UTP Transfer Request Descriptor (UTRD) - 32 bytes, host byte order for HC (LE in spec) */
+rt_packed(struct rt_utp_transfer_req_desc
+{
+ struct rt_ufs_request_desc_header header;
+ /* DW 4-5: UCD base address low/high dwords */
+ rt_uint32_t command_desc_base_addr_lo; /* 128-byte aligned, HC reads as LE */
+ rt_uint32_t command_desc_base_addr_hi; /* 128-byte aligned, HC reads as LE */
+ rt_uint16_t response_upiu_length;
+ rt_uint16_t response_upiu_offset;
+ rt_uint16_t prd_table_length;
+ rt_uint16_t prd_table_offset;
+});
+
+/* UTP Transfer Command Descriptor (UCD) - command_upiu + response_upiu + prd_table */
+struct rt_utp_transfer_cmd_desc
+{
+ rt_uint8_t command_upiu[RT_UFS_ALIGNED_UPIU_SIZE];
+ rt_uint8_t response_upiu[RT_UFS_ALIGNED_UPIU_SIZE];
+ struct rt_ufs_sg_entry prd_table[];
+};
+
+/* One slot: UCD size = 512 + 512 + N*16. N=1 for single buffer. */
+/*
+ * PRDT entries per slot.
+ * Partition probing may read multiple blocks with buffers not page-aligned,
+ * so we keep a generous entry count to safely split by page boundaries.
+ */
+#define RT_UFS_PRDT_ENTRIES_PER_SLOT 32
+#define RT_UFS_UCD_SIZE (RT_UFS_ALIGNED_UPIU_SIZE * 2 + sizeof(struct rt_ufs_sg_entry) * RT_UFS_PRDT_ENTRIES_PER_SLOT)
+
+struct rt_ufs_ops;
+struct rt_ufs_host;
+
+enum rt_ufs_notify_change_status
+{
+ RT_UFS_NOTIFY_CHANGE_STATUS_PRE,
+ RT_UFS_NOTIFY_CHANGE_STATUS_POST,
+};
+
+/* PA layer attributes for link gear / power mode (ufshcd_change_power_mode) */
+struct rt_ufs_pa_layer_attr
+{
+ rt_uint32_t gear_rx;
+ rt_uint32_t gear_tx;
+ rt_uint32_t lane_rx;
+ rt_uint32_t lane_tx;
+ rt_uint32_t pwr_rx; /* enum rt_ufs_pa_pwr_mode */
+ rt_uint32_t pwr_tx;
+ rt_uint32_t hs_rate; /* enum rt_ufs_pa_hs_rate when in FAST* mode */
+};
+
+struct rt_ufs_host
+{
+ struct rt_scsi_host parent;
+
+ void *regs;
+ int irq;
+
+ rt_uint32_t cap;
+ rt_uint32_t nutrs; /* Number of UTP transfer request slots, 1..32 */
+
+ const struct rt_ufs_ops *ops;
+
+ /* UTRL (UTRD list) base (must be 1KB aligned); we use slot0 only */
+ struct rt_utp_transfer_req_desc *utrd; /* Points to utrl_base[0] */
+ void *utrl_base; /* Full UTRL base */
+ rt_size_t utrl_size; /* Bytes */
+ rt_ubase_t utrl_handle;
+
+ /* UTMRL (UTMRD list) base (must be 1KB aligned); placeholder for now */
+ void *utmrl_base;
+ rt_size_t utmrl_size;
+ rt_ubase_t utmrl_handle;
+ rt_uint8_t utmrl_coherent;
+
+ rt_uint8_t *ucd_base; /* One UCD: command_upiu + response_upiu + prd_table */
+ rt_size_t ucd_size; /* RT_UFS_UCD_SIZE or platform value */
+ rt_ubase_t ucd_handle;
+ rt_uint8_t ucd_coherent;
+
+ /* Bounce buffer for small DMA I/O (avoid stack/unmapped buffers) */
+ rt_uint8_t *bounce;
+ rt_size_t bounce_size;
+ rt_ubase_t bounce_handle;
+
+ /* IRQ status snapshot (written by ISR, read by transfer thread) */
+ volatile rt_uint32_t irq_status;
+
+ struct rt_completion done;
+ struct rt_spinlock lock;
+
+ struct rt_ufs_pa_layer_attr pwr_active;
+ rt_uint8_t pwr_active_valid;
+ /**
+ * Raw AHIT register value. 0 = use RT_UFS_AHIT_DEFAULT when CAP reports Auto-H8 support.
+ * Write 0 via rt_ufs_auto_hibern8_set() to turn off auto-hibernate.
+ */
+ rt_uint32_t ahit;
+};
+
+struct rt_ufs_ops
+{
+ rt_err_t (*init)(struct rt_ufs_host *ufs);
+ rt_err_t (*exit)(struct rt_ufs_host *ufs);
+ rt_err_t (*reset)(struct rt_ufs_host *ufs);
+ rt_err_t (*link_startup_notify)(struct rt_ufs_host *ufs, enum rt_ufs_notify_change_status status);
+};
+
+rt_err_t rt_ufs_host_register(struct rt_ufs_host *ufs);
+rt_err_t rt_ufs_host_unregister(struct rt_ufs_host *ufs);
+
+/**
+ * @brief Send a UIC command and wait for completion
+ *
+ * Used during controller bring-up and in the link_startup_notify hook (e.g. DME_GET/SET,
+ * DME_LINK_STARTUP).
+ *
+ * @param ufs UFS host controller
+ * @param cmd UIC opcode (e.g. RT_UFS_CMDOP_DME_LINKSTARTUP)
+ * @param arg1 UIC command argument 1
+ * @param arg2 UIC argument 2; on return, low 8 bits contain the UIC result code
+ * @param arg3 UIC command argument 3
+ *
+ * @return RT_EOK on success, -RT_ETIMEOUT on timeout, -RT_ERROR on failure
+ */
+rt_err_t rt_ufs_uic_cmd_send(struct rt_ufs_host *ufs, rt_uint32_t cmd,
+ rt_uint32_t arg1, rt_uint32_t *arg2, rt_uint32_t arg3);
+
+/**
+ * @brief Apply default power/performance settings after the link is up
+ *
+ * Programs interrupt aggregation (UTRIACR) and, if the host supports it (CAP Auto-H8), the
+ * Auto-Hibernate idle timer (AHIT). Called from rt_ufs_host_register(); BSP code may call
+ * again after custom link training if needed.
+ *
+ * @param ufs UFS host controller
+ */
+void rt_ufs_pm_post_linkup(struct rt_ufs_host *ufs);
+
+/**
+ * @brief UIC DME_SET with UIC result check
+ *
+ * @param ufs UFS host controller
+ * @param attr_sel MIB selector (e.g. RT_UFS_UIC_ARG_MIB)
+ * @param value Attribute value written to UIC argument 3
+ *
+ * @return RT_EOK on success, otherwise an error code
+ */
+rt_err_t rt_ufs_dme_set(struct rt_ufs_host *ufs, rt_uint32_t attr_sel, rt_uint32_t value);
+
+/**
+ * @brief UIC DME_GET
+ *
+ * @param ufs UFS host controller
+ * @param attr_sel MIB selector
+ * @param value Storage for the attribute value read from UIC argument 3
+ *
+ * @return RT_EOK on success, otherwise an error code
+ */
+rt_err_t rt_ufs_dme_get(struct rt_ufs_host *ufs, rt_uint32_t attr_sel, rt_uint32_t *value);
+
+/**
+ * @brief Set PHY power mode via PA_PWRMODE
+ *
+ * @param ufs UFS host controller
+ * @param mode Encoded as (rx_mode << 4) | tx_mode (see UniPro PA power modes)
+ *
+ * @return RT_EOK on success, otherwise an error code
+ */
+rt_err_t rt_ufs_uic_pa_pwrmode(struct rt_ufs_host *ufs, rt_uint8_t mode);
+
+/**
+ * @brief Change PA layer gear, lanes, termination, HS series, and trigger power mode
+ *
+ * @param ufs UFS host controller
+ * @param attr Desired PA layer parameters
+ * @param force If true, apply even when attr matches the last successful configuration
+ *
+ * @return RT_EOK on success, otherwise an error code
+ */
+rt_err_t rt_ufs_pa_power_mode_set(struct rt_ufs_host *ufs, const struct rt_ufs_pa_layer_attr *attr, rt_bool_t force);
+
+/**
+ * @brief Request link Hibernate8 enter (UIC DME_HIBERNATE_ENTER)
+ *
+ * @param ufs UFS host controller
+ *
+ * @return RT_EOK on success, otherwise an error code
+ */
+rt_err_t rt_ufs_hibern8_enter(struct rt_ufs_host *ufs);
+
+/**
+ * @brief Request link Hibernate8 exit (UIC DME_HIBERNATE_EXIT)
+ *
+ * @param ufs UFS host controller
+ *
+ * @return RT_EOK on success, otherwise an error code
+ */
+rt_err_t rt_ufs_hibern8_exit(struct rt_ufs_host *ufs);
+
+/**
+ * @brief Program the Auto-Hibernate idle timer register (AHIT)
+ *
+ * Requires host capability RT_UFS_REG_CAP_AUTOH8. Pass 0 to disable auto-hibernate.
+ *
+ * @param ufs UFS host controller
+ * @param reg_val Raw AHIT register value
+ *
+ * @return RT_EOK on success, -RT_ENOSYS if Auto-H8 is not supported, otherwise an error code
+ */
+rt_err_t rt_ufs_auto_hibern8_set(struct rt_ufs_host *ufs, rt_uint32_t reg_val);
+
+/**
+ * @brief Configure UTP transfer completion interrupt aggregation (UTRIACR, offset 0x4C)
+ *
+ * @param ufs UFS host controller
+ * @param enable RT_TRUE to enable aggregation; RT_FALSE clears the register
+ * @param cnt Completion counter threshold before an interrupt (0–31)
+ * @param timeout Aggregation timeout in 40 µs steps (UFSHCI)
+ */
+void rt_ufs_intr_aggr_configure(struct rt_ufs_host *ufs, rt_bool_t enable, rt_uint8_t cnt, rt_uint8_t timeout);
+
+#endif /* __UFS_H__ */
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index 4914fe329c..d83311bcf9 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -135,6 +135,10 @@ extern "C" {
#include "drivers/thermal.h"
#endif /* RT_USING_THERMAL */
+#ifdef RT_USING_UFS
+#include "drivers/ufs.h"
+#endif /* RT_USING_UFS */
+
#ifdef RT_USING_FIRMWARE
#ifdef RT_FIRMWARE_ARM_SCMI
#include "drivers/scmi.h"