---
# System prepended metadata

title: 'UFS(1): 基礎篇'
tags: [' System Software', UFS, I/O]

---

---
tags: I/O, System Software
---

# UFS(1): 基礎篇

## Overview

[UFS(Universal Flash Storage)](https://en.wikipedia.org/wiki/Universal_Flash_Storage) 是由 [JEDEC](https://zh.wikipedia.org/wiki/JEDEC) 制定，設計用於數位相機、智慧型手機等消費電子產品使用的快閃記憶體(flash)儲存規範。近期，在車用上 UFS 的使用也獲得關注。它的設計目標是發展一套統一的 flash 存取介面，在提供高數據傳輸速度和穩定性的同時，也可以減少消費者對於市面上各種記憶卡格式的混淆和不同記憶卡轉接器的使用。

![image](https://hackmd.io/_uploads/S1OelPmubg.png =300x)


UFS 被視為 [eMMC](https://zh.wikipedia.org/wiki/%E5%A4%9A%E5%AA%92%E9%AB%94%E8%A8%98%E6%86%B6%E5%8D%A1) 和 SD 卡的取代品。相較於 EMMC 採 parallel 傳輸技術，UFS 使用頻寬可更高的 serial 傳輸。架構上，host 與 device 間的交互會由 UFS host controller 來管理。對 host，JEDEC 定義了 UFS host controller interface 作為軟體的統一存取介面;對 device 的存取則透過 UIC，後者包含物理層介面上的 MIPI [MPHY](https://en.wikipedia.org/wiki/M-PHY)，搭配 data link layer 上的 MIPI [UniPro](https://en.wikipedia.org/wiki/UniPro)。

下圖展示了在系統軟體架構中，UFS 設計的概觀。

![image](https://hackmd.io/_uploads/rJTPvv7dZl.png)

JEDEC 標準中的架構圖展示了設計的進階細節。

![image](https://hackmd.io/_uploads/rk7oTg73a.png)
> [JEDEC Publishes JESD220-2 Universal Flash Storage Card Extension Standard](https://www.storagenewsletter.com/2016/04/07/jedec-publishes-jesd220-2-universal-flash-storage-card-extension-standard/)

![image](https://hackmd.io/_uploads/SyL3w2NY0.png)
> [White Paer: Introduction to the Universal Flash Storage Assocation](https://ufsa.org/wp-content/uploads/2011/06/1306_UFSA_White_Paper.pdf)

截至撰文的目前為止，UFS 開發至 4.0 版本，最高可提供 5800 MB/s 的頻寬。

![image](https://hackmd.io/_uploads/rysObvmubl.png)

## UFS Application Layer

在 UFS 的應用層，host 的溝通是基於 [SCSI Architecture Model(SAM)](https://en.wikipedia.org/wiki/SCSI_architectural_model) 定義的 [SCSI](https://en.wikipedia.org/wiki/SCSI) 命令介面，命令透過 Command Descriptor Block(CBD) 結構形式組成。

每個 CDB 會是 6, 10 或 16 個 bytes 大小，並遵循 *I_T_L_Q nexus transaction*。這表示 CDB 需要識別與 **T**arget 中特定 **L**UN 通訊的 **I**nitiator，並執行特定的 **Q**uery。

### Logical Unit(LUN)
> [蛋蛋读UFS之五：逻辑单元（LU）](http://www.ssdfans.com/?p=92728)


在 SCSI 中導入了 Logical Unit(LUN) 的概念。一個儲存裝置(例如 UFS)可以被切分成數個 LUN，每個 LUN 有獨立的定址空間、大小、讀寫屬性、command queue、Memory Types 等等。

對於一個 UFS，最多可以有 32 個普通的 LUN，還可以有四個特別的 "Well known LUN":
- Report LUNS: 針對 SCSI 的 Report LUNs 命令，紀錄整個 UFS 中的 LUN 數量與設定的資訊
- UFS Device LUNS: 針對 SCSI 的 INQUIRY 命令，與不針對特定的普通 LUN 功能相關，例如格式化(FORMAT UNIT)、電源管理相關(START STOP UNIT)
- Boot LUNs: 與 UFS 的啟動相關，最多可以有兩個(LUN A and LUN B)
- RPMB(Replay Protected Memory Block): 與安全存取相關

對於 UFS 的初始化，SCSI Driver 會先透過 Report LUNs (A0h) 命令獲得 LUN 的清單，然後就可以藉由確認每個 LUN 的容量，建立對應的 block device(`/dev/sdx`)。

![image](https://hackmd.io/_uploads/SJbRg4PFWx.png)

## UFS Interconnect Layer(UIC)

UFS 中以 [MIPI-MPHY](https://en.wikipedia.org/wiki/M-PHY)) 定義物理層(physical layer)的實作，以 [MIPI Unipro](https://en.wikipedia.org/wiki/UniPro) 定義資料連結層(data link layer) 的實作。

下圖則展示了 UFS 中的訊號定義，包含了硬體重製(RST_N)、reference clock(REF_CLK)、即數據接收與發送的  differential pair(DIN 和 DOUT)。
![image](https://hackmd.io/_uploads/r1xgcr-k5-l.png)

而 UFS High-Speed (HS) Gear 則定義了在 MIPI M-PHY physical 層的最高 datarates，截至本文最高可達 [HS-Gear 6](https://www.mipi.org/knowledge-library/webinars/evolution-of-ufs-leveraging-m-phy-and-unipro-for-next-generation-performance-power-efficiency-and-reliability)，支援每個 lane 最高 46.6 Gbps 的速度。此外，UFS 可支援最多 2 個 lanes。

| HS-Gear   | Speed     |
|:--------- |:--------- |
| HS-Gear 1 | 1.5 Gbps  |
| HS-Gear 2 | 2.9 Gbp   |
| HS-Gear 3 | 5.8 Gbps  |
| HS-Gear 4 | 11.6 Gbps |
| HS-Gear 5 | 23.3 Gbps |
| HS-Gear6  | 46.6 Gbps |

## UFS Transport Layer


在 UFS 的傳輸層(transport layer) 中傳遞的封包稱為 **UPIU(UFS Protocol Information Units)**。UFS 的傳輸是採用 client-server 的模型，由 UFS host 作為 Client/Initiator 發送命令給 UFS device 的 Server/Target。後者在完成請求後再返回 repsonse。

一個 UFS 請求的進行可以分成三個階段:
* Command: Host 發起請求
* Data: 傳輸與 Command 相關的數據，不需要額外數據的命令可以略過此階段
* Response: Device 完成請求後，返回執行結果的資訊
    * 與 PCIe 不同，UFS 的命令都必須返回結果

這三個階段分別可以對應到三種 UPIU:
- Command UPIU
- Data UPIU
- Response UPIU

每種 UPIU 又可以依據應用區分成不同的類型，詳細可以對照 - [蛋蛋读UFS之三：UFS数据包UPIU](http://www.ssdfans.com/?p=92598) 的說明。

## Power Management

### Device Power Modes

UFS 裝置支援多種電源模式，這些模式由 START STOP UNIT(SSU) command 和一些 attribute 控制。Device power mode 獨立於 bus 上下游的 link 狀態。

在 UFS 標準中為裝置定義了數種電源模式。其中包含四種基本功耗模式。一種是裝置正在工作，一種是等待下一條指令，一種是已進入睡眠狀態並能在 host 需要時喚醒，還有一種是完全關閉電源的模式。此外，還需要三種過渡模式作為上述四種模式切換的中間狀態。

四種基本狀態分別是:
* Active: 裝置正在回應命令或在背景運作，又可以分成 16 個等級(ActiveCCLevel)
* Idle: 裝置未執行任何操作
* Sleep: 可顯著降低裝置的耗電量。在此狀態下，可以移除對 UFS 的供電(VCC)。此模式下任何 LUN 都不能被存取，也不能對 UFS 下 SSU 以外任何命令
* PowerDown: 此模式可以提供最大的省電量。在此狀態下可以移除所有供電。揮發性資料可能遺失

對應到 Linux 中的定義:
```cpp
/* UFS device power modes */
enum ufs_dev_pwr_mode {
	UFS_ACTIVE_PWR_MODE	= 1,
	UFS_SLEEP_PWR_MODE	= 2,
	UFS_POWERDOWN_PWR_MODE	= 3,
	UFS_DEEPSLEEP_PWR_MODE	= 4,
};
```

:::warning
註: 留意到省電等級與數字順序上的差異
:::


三種過度模式為:
* Pre-Active
* Pre-Sleep
* Pre-PowerDown

狀態的轉換則如下圖所示:

![image](https://hackmd.io/_uploads/HywkemQ3T.png)
> [Power Reduction and Low Risk Implementation of UFS v2.0 Design](https://www.jedec.org/sites/default/files/files/Hezi_Saar_MF_updated_9-22.pdf)


軟體要驅動電源模式的切換是透過 SSU(Start Stop Unit) command，在 Linux 中對應到 `ufshcd_set_dev_pwr_mode()`。command 格式如下:

![image](https://hackmd.io/_uploads/H1S9AXm2p.png)
> [ufs2.2 协议扫盲(七)](https://blog.csdn.net/haoyun1990/article/details/121890051)

特別值得注意的欄位有:
* OPCODE: 0x1B 為 SSU
* IMMED: 設為 0 的話，response 會在切換完成後才回傳，設為 1 則進入過渡期就會回傳
* POWER CONDITION(PC): 與 mode 轉換相關，留意到數值內容關聯至當前的 device power mode

Host 可以透過讀取 bCurrentPowerMode 屬性來檢索目前電源模式，以知道要切換到目標模式下 PC 的設定值。為此，bCurrentPowerMode 是裝置在任何電源模式下唯一都需要傳回的屬性。相對的，如果裝置未處於 active 或 idle 模式，則透過  QUERY REQUEST UPIU 存取 bCurrentPowerMode 以外的 descriptors、flags、attributes 的可能會失敗。

:::info
要取得 bCurrentPowerMode，在 Linux 下可以透過 sysfs 節點:

```
$ cat /sys/bus/platform/devices/<ufshci>/attributes/current_power_mode
```

或者是使用 [ufs-utils](https://github.com/westerndigitalcorporation/ufs-utils)，注意此種方式需要加上額外的 `CONFIG_SCSI_UFS_BSG` 進行編譯。
```
$ ufs-utils attr -t 2 -p /dev/bsg/ufs-bsg0
```
:::

### UIC Link State

UFS 中的 host 和裝置透過間以 M-PHY 連接，而 M-PHY 支援不同的模式和狀態，以達理想的傳輸速度或電源管理。如下圖，藍色方框中是低速模式(LS-MODE)的運作和省電狀態，紅色方框中則是高速模式(HS-MODE)的運作和省電狀態。

![image](https://hackmd.io/_uploads/B1FpZ9K3T.png)

![image](https://hackmd.io/_uploads/ryQwf9Y2p.png)
> [M-PHY Benefits and Challenges](https://mixel.com/m-phy-benefits-challenges/)

當沒有數據傳輸時，M-PHY 會自動切換到 STALL 或 SLEEP 狀態下。而 Host 可以通過 UFSHCI 的 UIC Command 暫存器(0x90) 透過 DME 來介入 UIC 層的行為，主動讓 M-PHY 狀態進入更為省電的 HIBERN8，即 `DME_HIBERNATE_ENTER`。 

對應到 Linux 有以下幾種定義，其中 `UIC_LINK_ACTIVE_STATE` 包含了 LS/HS/Sleep，畢竟這些狀態之間的轉換是由硬體進行，從軟體的角度來看可視為一致。

```cpp
/* 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_LINK_BROKEN_STATE	= 3, /* Link is in broken state */
};
```

:::warning
主要是設定為前三種其一
:::

### UFS PM Level

在 Linux 中，裝置進入 suspend/runtime suspend 時的 Device Power Modes 和 UIC Link State 組合是直接綁定的。

```cpp
const struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
    [UFS_PM_LVL_0] = {UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE},
    [UFS_PM_LVL_1] = {UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE},
    [UFS_PM_LVL_2] = {UFS_SLEEP_PWR_MODE, UIC_LINK_ACTIVE_STATE},
    [UFS_PM_LVL_3] = {UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
    [UFS_PM_LVL_4] = {UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
    [UFS_PM_LVL_5] = {UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
    [UFS_PM_LVL_6] = {UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE},
};
```

在 host controller driver 初始化階段設置好 `hba->spm_lvl` 和 `hba->rpm_lvl` 後，UFS core 將會在 suspend/runtime suspend 階段依此設定將裝置調整到對應的狀態。

### Auto-Hibernation

查看 Capabilities registers 中的 Controller capabilities 可以知道 host controller 是否支援 auto hibernation。在支援該功能的 host controller 加上額外設定 Auto-Hibernate Idle Timer register(AHIT) 可允許 link 在設置的 idle 時間後，硬體自動發送 `DME_HIBERNATE_ENTER` 來進入 HIBERN8。

## UFSHCI

UFS Host controller interface (UFSHCI)是 Host 控制 UFS 裝置的介面，具體是透過使用相關暫存器和 request descriptors 來使 host contorller 對裝置完成請求。

UFSHCI 定義了兩種 interface space:
* MMIO space: 在這個空間含有系統軟體可存取的一組硬體暫存器，映射到 host 的記憶體空間中
* Host memory space: 此空間包括提供執行命令的 descriptor 以及每個命令部分的資料的 buffer



## Reference

- [What is Universal Flash Storage (UFS)](https://www.synopsys.com/glossary/what-is-universal-flash-storage.html)
- [Overview of Universal Flash Storage Subsystem - Mohammad Faiz Abbas Rizvi, Texas Instruments India](https://www.youtube.com/watch?v=ZxWnRcyS2FU)
- [Introduction to UFS Subsystem](https://elinux.org/images/6/64/Introduction_to_UFS.pdf)
- [UFS 学习笔记（概念入门篇）](https://zhuanlan.zhihu.com/p/663057180)
- [UFS Hibernate 介紹 - 協議](https://blog.csdn.net/guozhidixian/article/details/124361506)
- [UFS Hibernate 介紹 - 代碼](https://blog.csdn.net/guozhidixian/article/details/124648915)
- [蛋蛋读UFS之三：UFS数据包UPIU](http://www.ssdfans.com/?p=92598)
- [蛋蛋读UFS之十：UFS电源管理](http://www.ssdfans.com/?p=92792)