364 lines
13 KiB
C
364 lines
13 KiB
C
/* $OpenBSD: ufshcireg.h,v 1.7 2024/05/09 08:20:22 mglocker Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
* Generic parameters.
|
|
*/
|
|
#define UFSHCI_UCD_PRDT_MAX_SEGS 64
|
|
#define UFSHCI_UCD_PRDT_MAX_XFER (UFSHCI_UCD_PRDT_MAX_SEGS * PAGE_SIZE)
|
|
#define UFSHCI_INTR_AGGR_TIMEOUT 0x64 /* 4ms */
|
|
#define UFSHCI_MAX_UNITS 32
|
|
|
|
/*
|
|
* Controller Capabilities Registers
|
|
*/
|
|
|
|
/* Controller Capabilities */
|
|
#define UFSHCI_REG_CAP 0x00
|
|
#define UFSHCI_REG_CAP_CS (1 << 28) /* RO */
|
|
#define UFSHCI_REG_CAP_UICDMETMS (1 << 26) /* RO */
|
|
#define UFSHCI_REG_CAP_OODDS (1 << 25) /* RO */
|
|
#define UFSHCI_REG_CAP_64AS (1 << 24) /* RO */
|
|
#define UFSHCI_REG_AUTOH8 (1 << 23) /* RO */
|
|
#define UFSHCI_REG_CAP_NUTMRS(x) ((x >> 16) & 0x00000007) /* RO */
|
|
#define UFSHCI_REG_CAP_RTT(x) ((x >> 8) & 0x000000ff) /* RO */
|
|
#define UFSHCI_REG_CAP_NUTRS(x) ((x >> 0) & 0x0000001f) /* RO */
|
|
/* UFS Version in BCD format */
|
|
#define UFSHCI_REG_VER 0x08
|
|
#define UFSHCI_REG_VER_MAJOR(x) ((x >> 8) & 0x0000000f) /* RO */
|
|
#define UFSHCI_REG_VER_MINOR(x) ((x >> 4) & 0x0000000f) /* RO */
|
|
#define UFSHCI_REG_VER_SUFFIX(x) ((x >> 0) & 0x0000000f) /* RO */
|
|
/* Product ID */
|
|
#define UFSHCI_REG_HCPID 0x10
|
|
/* Manufacturer ID */
|
|
#define UFSHCI_REG_HCMID 0x14
|
|
#define UFSHCI_REG_HCMID_BI(x) ((x >> 8) & 0x000000ff) /* RO */
|
|
#define UFSHCI_REG_HCMID_MIC(x) ((x >> 0) & 0x000000ff) /* RO */
|
|
/* Auto-Hibernate Idle Timer */
|
|
#define UFSHCI_REG_AHIT 0x18
|
|
|
|
/*
|
|
* Operation and Runtime Registers
|
|
*/
|
|
|
|
/* Interrupt Status */
|
|
#define UFSHCI_REG_IS 0x20
|
|
#define UFSHCI_REG_IS_CEFES (1 << 18) /* RWC */
|
|
#define UFSHCI_REG_IS_SBFES (1 << 17) /* RWC */
|
|
#define UFSHCI_REG_IS_HCFES (1 << 16) /* RWC */
|
|
#define UFSHCI_REG_IS_UTPES (1 << 12) /* RWC */
|
|
#define UFSHCI_REG_IS_DFES (1 << 11) /* RWC */
|
|
#define UFSHCI_REG_IS_UCCS (1 << 10) /* RWC */
|
|
#define UFSHCI_REG_IS_UTMRCS (1 << 9) /* RWC */
|
|
#define UFSHCI_REG_IS_ULSS (1 << 8) /* RWC */
|
|
#define UFSHCI_REG_IS_ULLS (1 << 7) /* RWC */
|
|
#define UFSHCI_REG_IS_UHES (1 << 6) /* RWC */
|
|
#define UFSHCI_REG_IS_UHXS (1 << 5) /* RWC */
|
|
#define UFSHCI_REG_IS_UPMS (1 << 4) /* RWC */
|
|
#define UFSHCI_REG_IS_UTMS (1 << 3) /* RWC */
|
|
#define UFSHCI_REG_IS_UE (1 << 2) /* RWC */
|
|
#define UFSHCI_REG_IS_UDEPRI (1 << 1) /* RWC */
|
|
#define UFSHCI_REG_IS_UTRCS (1 << 0) /* RWC */
|
|
/* Interrupt Enable */
|
|
#define UFSHCI_REG_IE 0x24
|
|
#define UFSHCI_REG_IE_CEFFE (1 << 18) /* RW */
|
|
#define UFSHCI_REG_IE_SBFEE (1 << 17) /* RW */
|
|
#define UFSHCI_REG_IE_HCFEE (1 << 16) /* RW */
|
|
#define UFSHCI_REG_IE_UTPEE (1 << 12) /* RW */
|
|
#define UFSHCI_REG_IE_DFEE (1 << 11) /* RW */
|
|
#define UFSHCI_REG_IE_UCCE (1 << 10) /* RW */
|
|
#define UFSHCI_REG_IE_UTMRCE (1 << 9) /* RW */
|
|
#define UFSHCI_REG_IE_ULSSE (1 << 8) /* RW */
|
|
#define UFSHCI_REG_IE_ULLSE (1 << 7) /* RW */
|
|
#define UFSHCI_REG_IE_UHESE (1 << 6) /* RW */
|
|
#define UFSHCI_REG_IE_UHXSE (1 << 5) /* RW */
|
|
#define UFSHCI_REG_IE_UPMSE (1 << 4) /* RW */
|
|
#define UFSHCI_REG_IE_UTMSE (1 << 3) /* RW */
|
|
#define UFSHCI_REG_IE_UEE (1 << 2) /* RW */
|
|
#define UFSHCI_REG_IE_UDEPRIE (1 << 1) /* RW */
|
|
#define UFSHCI_REG_IE_UTRCE (1 << 0) /* RW */
|
|
/* Host Controller Status */
|
|
#define UFSHCI_REG_HCS 0x30
|
|
#define UFSHCI_REG_HCS_TLUNUTPE(x) ((x << 24) & 0xff000000) /* RO */
|
|
#define UFSHCI_REG_HCS_TTAGUTPE(x) ((x << 16) & 0x00ff0000) /* RO */
|
|
#define UFSHCI_REG_HCS_UTPEC(x) ((x << 12) & 0x0000f000) /* RO */
|
|
#define UFSHCI_REG_HCS_UPMCRS(x) ((x << 8) & 0x00000700) /* RO */
|
|
#define UFSHCI_REG_HCS_UCRDY (1 << 3) /* RO */
|
|
#define UFSHCI_REG_HCS_UTMRLRDY (1 << 2) /* RO */
|
|
#define UFSHCI_REG_HCS_UTRLRDY (1 << 1) /* RO */
|
|
#define UFSHCI_REG_HCS_DP (1 << 0) /* RO */
|
|
/* Host Controller Enable */
|
|
#define UFSHCI_REG_HCE 0x34
|
|
#define UFSHCI_REG_HCE_CGE (1 << 1) /* RW */
|
|
#define UFSHCI_REG_HCE_HCE (1 << 0) /* RW */
|
|
/* Host UIC Error Code PHY Adapter Layer */
|
|
#define UFSHCI_REG_UECPA 0x38
|
|
/* Host UIC Error Code Data Link Layer */
|
|
#define UFSHCI_REG_UECDL 0x3C
|
|
/* Host UIC Error Code Network Layer */
|
|
#define UFSHCI_REG_UECN 0x40
|
|
/* Host UIC Error Code Transport Layer */
|
|
#define UFSHCI_REG_UECT 0x44
|
|
/* Host UIC Error Code */
|
|
#define UFSHCI_REG_UECDME 0x48
|
|
/* UTP Transfer Request Interrupt Aggregation Control Register */
|
|
#define UFSHCI_REG_UTRIACR 0x4C
|
|
#define UFSHCI_REG_UTRIACR_IAEN (1U << 31) /* RW */
|
|
#define UFSHCI_REG_UTRIACR_IAPWEN (1 << 24) /* WO */
|
|
#define UFSHCI_REG_UTRIACR_IASB (1 << 20) /* RO */
|
|
#define UFSHCI_REG_UTRIACR_CTR (1 << 16) /* WO */
|
|
#define UFSHCI_REG_UTRIACR_IACTH(x) (x << 8) /* RW, max. val = 31 */
|
|
#define UFSHCI_REG_UTRIACR_IATOVAL(x) (x << 0) /* RW, 40us units (1=40us) */
|
|
|
|
/*
|
|
* UTP Transfer Request List Registers
|
|
*/
|
|
|
|
/* Base Address */
|
|
#define UFSHCI_REG_UTRLBA 0x50 /* RW */
|
|
/* Base Address Upper 32-bits */
|
|
#define UFSHCI_REG_UTRLBAU 0x54 /* RW */
|
|
/* Door Bell Register */
|
|
#define UFSHCI_REG_UTRLDBR 0x58 /* RWS */
|
|
/* Clear Register */
|
|
#define UFSHCI_REG_UTRLCLR 0x5C /* WO */
|
|
/* Run-Stop Register */
|
|
#define UFSHCI_REG_UTRLRSR 0x60 /* RW */
|
|
#define UFSHCI_REG_UTRLRSR_STOP 0x00
|
|
#define UFSHCI_REG_UTRLRSR_START 0x01
|
|
/* Completion Notification Register */
|
|
#define UFSHCI_REG_UTRLCNR 0x64 /* RWC */
|
|
|
|
/*
|
|
* UTP Task Management Request List Registers
|
|
*/
|
|
|
|
/* Base Address */
|
|
#define UFSHCI_REG_UTMRLBA 0x70 /* RW */
|
|
/* Base Address Upper 32-bits */
|
|
#define UFSHCI_REG_UTMRLBAU 0x74 /* RW */
|
|
/* Door Bell Register */
|
|
#define UFSHCI_REG_UTMRLDBR 0x78 /* RWS */
|
|
/* Clear Register */
|
|
#define UFSHCI_REG_UTMRLCLR 0x7C /* WO */
|
|
/* Run-Stop Register */
|
|
#define UFSHCI_REG_UTMRLRSR 0x80 /* RW */
|
|
#define UFSHCI_REG_UTMRLRSR_STOP 0x00
|
|
#define UFSHCI_REG_UTMRLRSR_START 0x01
|
|
|
|
/*
|
|
* UIC Command Registers
|
|
*/
|
|
|
|
/* UIC Command Register */
|
|
#define UFSHCI_REG_UICCMD 0x90
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_GET 0x01 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_SET 0x02 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_PEER_GET 0x03 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_PEER_SET 0x04 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_POWERON 0x10 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_POWEROFF 0x11 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_ENABLE 0x12 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_RESET 0x14 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_ENDPOINTRESET 0x15 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_LINKSTARTUP 0x16 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_HIBERNATE_ENTER 0x17 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_HIBERNATE_EXIT 0x18 /* RW */
|
|
#define UFSHCI_REG_UICCMD_CMDOP_DME_TEST_MODE 0x1A /* RW */
|
|
/* UIC Command Argument 1 */
|
|
#define UFSHCI_REG_UICCMDARG1 0x94
|
|
/* UIC Command Argument 2 */
|
|
#define UFSHCI_REG_UICCMDARG2 0x98
|
|
/* UIC Command Argument 3 */
|
|
#define UFSHCI_REG_UICCMDARG3 0x9C
|
|
|
|
/*
|
|
* Vendor Specific Registers (0xC0 - 0xFF)
|
|
*/
|
|
|
|
/*
|
|
* UTP Transfer Request Descriptor Structure
|
|
*/
|
|
|
|
/* Command Type (CT) */
|
|
#define UFSHCI_UTRD_DW0_CT_UFS (1 << 28) /* UFS Storage */
|
|
/* Data Direction (DD) */
|
|
#define UFSHCI_UTRD_DW0_DD_NO (0 << 25) /* No transfer */
|
|
#define UFSHCI_UTRD_DW0_DD_I2T (1 << 25) /* From Initiator to Target */
|
|
#define UFSHCI_UTRD_DW0_DD_T2I (2 << 25) /* From Target to Initiator */
|
|
/* Interrupt (I) */
|
|
#define UFSHCI_UTRD_DW0_I_REG (0 << 24) /* Regular Command */
|
|
#define UFSHCI_UTRD_DW0_I_INT (1 << 24) /* Interrupt Command */
|
|
/* Crypto Enable (CE) */
|
|
#define UFSHCI_UTRD_DW0_CE_DISABLE (0 << 23) /* Disable Crypto */
|
|
#define UFSHCI_UTRD_DW0_CE_ENABLE (1 << 23) /* Enable Crypto */
|
|
/* Crypto Configuration Index (CCI) */
|
|
#define UFSHCI_UTRD_DW0_CCI(x) (x & 0x000000ff)
|
|
|
|
/* Data Unit Number Upper 32-bits (DUNL) */
|
|
#define UFSHCI_UTRD_DW1_DUNL(x) (x << 0)
|
|
|
|
/* Overall Command Status (OCS) */
|
|
#define UFSHCI_UTRD_DW2_OCS(x) (x & 0x000000ff)
|
|
#define UFSHCI_UTRD_DW2_OCS_SUCCESS 0x00 /* Success */
|
|
#define UFSHCI_UTRD_DW2_OCS_ICTA 0x01 /* Invalid Command Table Attr. */
|
|
#define UFSHCI_UTRD_DW2_OCS_IPA 0x02 /* Invalid PRDT Attr. */
|
|
#define UFSHCI_UTRD_DW2_OCS_MDBS 0x03 /* Mismatch Data Buffer Size */
|
|
#define UFSHCI_UTRD_DW2_OCS_MRUS 0x04 /* Mismatch Response UPIU Size */
|
|
#define UFSHCI_UTRD_DW2_OCS_CF 0x05 /* Communication Failure */
|
|
#define UFSHCI_UTRD_DW2_OCS_ABRT 0x06 /* Aborted */
|
|
#define UFSHCI_UTRD_DW2_OCS_FE 0x07 /* Fatal Error */
|
|
#define UFSHCI_UTRD_DW2_OCS_DFE 0x08 /* Device Fatal Error */
|
|
#define UFSHCI_UTRD_DW2_OCS_ICC 0x09 /* Invalid Crypto Configuration */
|
|
#define UFSHCI_UTRD_DW2_OCS_GCE 0x0A /* General Crypto Error */
|
|
#define UFSHCI_UTRD_DW2_OCS_IOV 0x0F /* Invalid OCS Value */
|
|
|
|
/* Data Unit Number Upper 32-bits Upper 32-bits (DUNU) */
|
|
#define UFSHCI_UTRD_DW3_DUNU(x) (x << 0)
|
|
|
|
/* UTP Command Descriptor Base Address (UCDBA) */
|
|
#define UFSHCI_UTRD_DW4_UCDBA(x) (x << 7)
|
|
|
|
/* UTP Command Descriptor Base Address Upper 32-bits (UCDBAU) */
|
|
#define UFSHCI_UTRD_DW5_UCDBAU(x) (x << 0)
|
|
|
|
/* Response UPIU Offset (RUO) */
|
|
#define UFSHCI_UTRD_DW6_RUO(x) (x << 16)
|
|
/* Response UPIU Length (RUL) */
|
|
#define UFSHCI_UTRD_DW6_RUL(x) (x & 0x0000ffff)
|
|
|
|
/* PRDT Offset (PRDTO) */
|
|
#define UFSHCI_UTRD_DW7_PRDTO(x) (x << 16)
|
|
/* PRDT Length (PRDTL) */
|
|
#define UFSHCI_UTRD_DW7_PRDTL(x) (x & 0x0000ffff)
|
|
|
|
struct ufshci_utrd {
|
|
uint32_t dw0; /* CT, DD, I, CE, CCI */
|
|
uint32_t dw1; /* Data Unit Number Lower 32-bits (DUNL) */
|
|
uint32_t dw2; /* OCS */
|
|
uint32_t dw3; /* Data Unit Number Upper 32-bits (DUNU) */
|
|
uint32_t dw4; /* UTP Cmd. Desc. Base Addr. Lower 32-bits (UCDBA) */
|
|
uint32_t dw5; /* UTP Cmd. Desc. Base Addr. Upper 32-bits (UCDBAU) */
|
|
uint32_t dw6; /* RUO, RUL */
|
|
uint32_t dw7; /* PRDTO, PRDTL */
|
|
} __packed;
|
|
|
|
/*
|
|
* UTP Command Descriptor, PRDT (Physical Region Description Table) Structure
|
|
*/
|
|
|
|
/* Data Base Address (DBA) */
|
|
#define UFSHCI_UCD_DW0_DBA(x) (x & 0xfffffffc)
|
|
|
|
/* Data Byte Count (DBC) */
|
|
#define UFSHCI_UCD_DW3_DBC(x) (x & 0x0003ffff)
|
|
|
|
struct ufshci_ucd_prdt {
|
|
uint32_t dw0; /* Data base Address Lower 32-bits (DBA) */
|
|
uint32_t dw1; /* Data base Address Upper 32-bits (DBAU) */
|
|
uint32_t dw2; /* Reserved */
|
|
uint32_t dw3; /* Data Byte Count (DBC) */
|
|
} __packed;
|
|
|
|
/*
|
|
* UTP Task Management Request Descriptor Structure
|
|
*/
|
|
|
|
/* Interrupt (I) */
|
|
#define UFSHCI_UTMRD_DW0_I_DISABLE (0 << 24)
|
|
#define UFSHCI_UTMRD_DW0_I_ENABLE (1 << 24)
|
|
|
|
/* Overall Command Status (OCS) */
|
|
#define UFSHCI_UTMRD_DW2_OCS(x) (x & 0x000000ff)
|
|
#define UFSHCI_UTMRD_DW2_OCS_SUCCESS 0x00 /* Success */
|
|
#define UFSHCI_UTMRD_DW2_OCS_ICTA 0x01 /* Invalid Command Table Attr. */
|
|
#define UFSHCI_UTMRD_DW2_OCS_IPA 0x02 /* Invalid PRDT Attr. */
|
|
#define UFSHCI_UTMRD_DW2_OCS_MDBS 0x03 /* Mismatch Data Buffer Size */
|
|
#define UFSHCI_UTMRD_DW2_OCS_MRUS 0x04 /* Mismatch Response UPIU Size */
|
|
#define UFSHCI_UTMRD_DW2_OCS_CF 0x05 /* Communication Failure */
|
|
#define UFSHCI_UTMRD_DW2_OCS_ABRT 0x06 /* Aborted */
|
|
#define UFSHCI_UTMRD_DW2_OCS_FE 0x07 /* Fatal Error */
|
|
#define UFSHCI_UTMRD_DW2_OCS_DFE 0x08 /* Device Fatal Error */
|
|
#define UFSHCI_UTMRD_DW2_OCS_ICC 0x09 /* Invalid Crypto Configuration */
|
|
#define UFSHCI_UTMRD_DW2_OCS_GCE 0x0A /* General Crypto Error */
|
|
#define UFSHCI_UTMRD_DW2_OCS_IOV 0x0F /* Invalid OCS Value */
|
|
|
|
struct ufshci_utmrd {
|
|
uint32_t dw0; /* I */
|
|
uint32_t dw1; /* Reserved */
|
|
uint32_t dw2; /* OCS */
|
|
uint32_t dw3; /* Reserved */
|
|
uint8_t dw4_w11[32]; /* Task Management Request UPIU */
|
|
uint8_t dw12_dw19[32]; /* Task Management Response UPIU */
|
|
} __packed;
|
|
|
|
/*
|
|
* ****************************************************************************
|
|
* Universal Flash Storage (UFS) Version 2.1 Specs from JESD220C
|
|
* ****************************************************************************
|
|
*/
|
|
|
|
/* UPIU structures are in Big Endian! */
|
|
|
|
#define UPIU_TC_I2T_NOP_OUT 0x00
|
|
#define UPIU_TC_I2T_COMMAND 0x01
|
|
#define UPIU_TC_I2T_DATA_OUT 0x02
|
|
#define UPIU_TC_I2T_TMR 0x04
|
|
#define UPIU_TC_I2T_QUERY_REQUEST 0x16
|
|
#define UPIU_TC_T2I_NOP_IN 0x20
|
|
#define UPIU_TC_T2I_RESPONSE 0x21
|
|
#define UPIU_TC_T2I_DATA_IN 0x22
|
|
#define UPIU_TC_T2I_TMR 0x24
|
|
#define UPIU_TC_T2I_QUERY_RESPONSE 0x36
|
|
#define UPIU_TC_T2I_REJECT 0x3f
|
|
|
|
#define UPIU_SCSI_RSP_INQUIRY_SIZE 36
|
|
#define UPIU_SCSI_RSP_CAPACITY16_SIZE 32
|
|
#define UPIU_SCSI_RSP_CAPACITY_SIZE 8
|
|
|
|
struct upiu_hdr {
|
|
uint8_t tc; /* Transaction Code */
|
|
uint8_t flags;
|
|
uint8_t lun;
|
|
uint8_t taskid;
|
|
uint8_t cmd_set_type;
|
|
uint8_t query;
|
|
uint8_t response;
|
|
uint8_t status;
|
|
uint8_t ehs_len;
|
|
uint8_t device_info;
|
|
uint16_t ds_len; /* Data Segment Length */
|
|
} __packed;
|
|
|
|
struct upiu_command {
|
|
struct upiu_hdr hdr;
|
|
uint32_t expected_xfer_len;
|
|
uint8_t cdb[16];
|
|
} __packed;
|
|
|
|
struct upiu_response {
|
|
struct upiu_hdr hdr;
|
|
uint32_t residual_xfer_len;
|
|
uint8_t cdb[16];
|
|
} __packed;
|
|
|
|
struct ufshci_ucd {
|
|
struct upiu_command cmd;
|
|
struct upiu_response rsp;
|
|
struct ufshci_ucd_prdt prdt[UFSHCI_UCD_PRDT_MAX_SEGS];
|
|
} __packed __aligned(128);
|