mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
ufshci: set HS series per platform and adapt type per gear
The driver always asked for Rate-B. It never set the adaptation type. The Snapdragon X Elite firmware tunes the PHY for Rate-A. A Rate-B link dies at every gear there. HS-G4 and above need initial adaptation. This is a UniPro rule. It applies to every host. Add an hs_series field to the device tables. Use Rate-A on the Snapdragon X Elite. Keep Rate-B on the PCI hosts. A table entry without an HS series fails to attach. Set PA_TxHsAdaptType to initial adaptation at HS-G4 and above. Leave it alone below that. Hosts before UniPro 1.8 do not have it. The Galaxy Book 4 Edge now links at HS-G5 Rate-A. fio results (128k sequential, 4k random, posixaio): QD | SEQ_R(MiB/s) | SEQ_W(MiB/s) | RND_R(kIOPS) | RND_W(kIOPS) ----+--------------+--------------+--------------+------------- 1 | 1357 | 1221 | 12.1 | 27.2 4 | 3103 | 3234 | 46.5 | 92.9 32 | 3508 | 3238 | 176.4 | 125.0 Sequential writes land in the WriteBooster buffer. Sustained writes drop to 556 MiB/s once the buffer runs out. Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D59298
This commit is contained in:
1 parent
973783515e
commit
c09daa33d6
6 files changed
+33
-9
No files matched your search
@@ -41,6 +41,8 @@
|
||||
#define PA_TxTermination 0x1569
|
||||
#define PA_RxTermination 0x1584
|
||||
#define PA_HSSeries 0x156A
|
||||
#define UFSHCI_HS_SERIES_A 1
|
||||
#define UFSHCI_HS_SERIES_B 2
|
||||
#define PA_PWRModeUserData0 0x15B0
|
||||
#define PA_PWRModeUserData1 0x15B1
|
||||
#define PA_PWRModeUserData2 0x15B2
|
||||
@@ -49,6 +51,8 @@
|
||||
#define PA_PWRModeUserData5 0x15B5
|
||||
|
||||
#define PA_TxHsAdaptType 0x15D4
|
||||
#define PA_INITIAL_ADAPT 1
|
||||
#define PA_NO_ADAPT 3
|
||||
#define PA_PWRMode 0x1571
|
||||
|
||||
#define DME_LocalFC0ProtectionTimeOutVal 0xD041
|
||||
|
||||
@@ -49,17 +49,21 @@ static struct ufshci_acpi_device {
|
||||
const char *hid;
|
||||
const char *desc;
|
||||
uint32_t ref_clk;
|
||||
uint32_t hs_series;
|
||||
uint32_t quirks;
|
||||
} ufshci_acpi_devices[] = {
|
||||
/*
|
||||
* The SoC feeds the device 38.4 MHz from its CXO. The firmware
|
||||
* has no property for it. Verified on the Galaxy Book 4 Edge.
|
||||
*
|
||||
* The firmware calibrates the PHY for Rate-A. A Rate-B link
|
||||
* comes up dead at every gear.
|
||||
*/
|
||||
{ "QCOM24A5", "Qualcomm Snapdragon X Elite UFS Host Controller",
|
||||
UFSHCI_REF_CLK_38_4MHz,
|
||||
UFSHCI_REF_CLK_38_4MHz, UFSHCI_HS_SERIES_A,
|
||||
UFSHCI_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH |
|
||||
UFSHCI_QUIRK_BROKEN_LSDBS_MCQS_CAP },
|
||||
{ 0x00000000, NULL, 0, 0 }
|
||||
{ 0x00000000, NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static char *ufshci_acpi_ids[] = { "QCOM24A5", NULL };
|
||||
@@ -97,6 +101,7 @@ ufshci_acpi_probe(device_t dev)
|
||||
if (acpi_dev->hid) {
|
||||
ctrlr->quirks = acpi_dev->quirks;
|
||||
ctrlr->ref_clk = acpi_dev->ref_clk;
|
||||
ctrlr->hs_series = acpi_dev->hs_series;
|
||||
}
|
||||
|
||||
if (acpi_dev->desc) {
|
||||
|
||||
@@ -375,6 +375,13 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev)
|
||||
if (!(ctrlr->is_single_db_supported || ctrlr->is_mcq_supported))
|
||||
return (ENXIO);
|
||||
|
||||
/* Every device table entry must name the HS series. */
|
||||
if (ctrlr->hs_series == 0) {
|
||||
ufshci_printf(ctrlr,
|
||||
"hs_series is missing from the device table\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* The maximum transfer size supported by UFSHCI spec is 65535 * 256 KiB
|
||||
* However, we limit the maximum transfer size to 1MiB(256 * 4KiB) for
|
||||
|
||||
@@ -320,8 +320,6 @@ ufshci_dev_init_unipro(struct ufshci_controller *ctrlr)
|
||||
int
|
||||
ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr)
|
||||
{
|
||||
/* HSSerise: A = 1, B = 2 */
|
||||
const uint32_t hs_series = 2;
|
||||
/*
|
||||
* TX/RX PWRMode:
|
||||
* - TX[3:0], RX[7:4]
|
||||
@@ -386,8 +384,13 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr)
|
||||
if (ufshci_uic_send_dme_set(ctrlr, PA_RxTermination, true))
|
||||
return (ENXIO);
|
||||
|
||||
/* Set HSSerise (A = 1, B = 2) */
|
||||
if (ufshci_uic_send_dme_set(ctrlr, PA_HSSeries, hs_series))
|
||||
/* Set HSSeries */
|
||||
if (ufshci_uic_send_dme_set(ctrlr, PA_HSSeries, ctrlr->hs_series))
|
||||
return (ENXIO);
|
||||
|
||||
/* HS-G4 and above need initial adaptation. */
|
||||
if (ctrlr->hs_gear >= 4 &&
|
||||
ufshci_uic_send_dme_set(ctrlr, PA_TxHsAdaptType, PA_INITIAL_ADAPT))
|
||||
return (ENXIO);
|
||||
|
||||
/* Set Timeout values */
|
||||
|
||||
@@ -49,20 +49,23 @@ static struct _pcsid {
|
||||
uint32_t devid;
|
||||
const char *desc;
|
||||
uint32_t ref_clk;
|
||||
uint32_t hs_series;
|
||||
uint32_t quirks;
|
||||
} pci_ids[] = { { 0x131b36, "QEMU UFS Host Controller", UFSHCI_REF_CLK_19_2MHz,
|
||||
UFSHCI_HS_SERIES_B,
|
||||
UFSHCI_QUIRK_IGNORE_UIC_POWER_MODE |
|
||||
UFSHCI_QUIRK_NOT_SUPPORT_ABORT_TASK |
|
||||
UFSHCI_QUIRK_SKIP_WELL_KNOWN_LUNS },
|
||||
{ 0x98fa8086, "Intel Lakefield UFS Host Controller",
|
||||
UFSHCI_REF_CLK_19_2MHz,
|
||||
UFSHCI_REF_CLK_19_2MHz, UFSHCI_HS_SERIES_B,
|
||||
UFSHCI_QUIRK_LONG_PEER_PA_TACTIVATE |
|
||||
UFSHCI_QUIRK_WAIT_AFTER_POWER_MODE_CHANGE |
|
||||
UFSHCI_QUIRK_CHANGE_LANE_AND_GEAR_SEPARATELY |
|
||||
UFSHCI_QUIRK_BROKEN_AUTO_HIBERNATE },
|
||||
{ 0x54ff8086, "Intel Alder Lake-N UFS Host Controller",
|
||||
UFSHCI_REF_CLK_19_2MHz, UFSHCI_QUIRK_BROKEN_AUTO_HIBERNATE },
|
||||
{ 0x00000000, NULL } };
|
||||
UFSHCI_REF_CLK_19_2MHz, UFSHCI_HS_SERIES_B,
|
||||
UFSHCI_QUIRK_BROKEN_AUTO_HIBERNATE },
|
||||
{ 0x00000000, NULL, 0, 0, 0 } };
|
||||
|
||||
static int
|
||||
ufshci_pci_probe(device_t device)
|
||||
@@ -77,6 +80,7 @@ ufshci_pci_probe(device_t device)
|
||||
if (ep->devid) {
|
||||
ctrlr->quirks = ep->quirks;
|
||||
ctrlr->ref_clk = ep->ref_clk;
|
||||
ctrlr->hs_series = ep->hs_series;
|
||||
}
|
||||
|
||||
if (ep->desc) {
|
||||
|
||||
@@ -326,6 +326,7 @@ struct ufshci_controller {
|
||||
256 /* Some controllers have their LSDB and MCQS fields reset to 0. */
|
||||
|
||||
uint32_t ref_clk;
|
||||
uint32_t hs_series;
|
||||
|
||||
struct cam_sim *ufshci_sim;
|
||||
struct cam_path *ufshci_path;
|
||||
|
||||
Reference in new issue
Block a user