From 9251d8a3d62b18fbf1e0fcc83036d282fcf226bb Mon Sep 17 00:00:00 2001 From: mglocker Date: Fri, 24 May 2024 20:34:06 +0000 Subject: [PATCH] Enable UFS "Auto-Hibernation". From the documentation: Auto-hibernate allows the host controller to put UniPro link into Hibernate state autonomously. --- sys/dev/ic/ufshci.c | 31 +++++++++++++++++++++++++++---- sys/dev/ic/ufshcireg.h | 9 ++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/sys/dev/ic/ufshci.c b/sys/dev/ic/ufshci.c index 7b04d3eb30d..cf969e41ef1 100644 --- a/sys/dev/ic/ufshci.c +++ b/sys/dev/ic/ufshci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufshci.c,v 1.31 2024/05/24 09:51:14 mglocker Exp $ */ +/* $OpenBSD: ufshci.c,v 1.32 2024/05/24 20:34:06 mglocker Exp $ */ /* * Copyright (c) 2022 Marcus Glocker @@ -111,7 +111,7 @@ int ufshci_intr(void *arg) { struct ufshci_softc *sc = arg; - uint32_t status; + uint32_t status, hcs; int handled = 0; status = UFSHCI_READ_4(sc, UFSHCI_REG_IS); @@ -131,6 +131,17 @@ ufshci_intr(void *arg) handled = 1; } + /* If Auto-Hibernate raises an interrupt, it's to yield an error. */ + if (status & UFSHCI_REG_IS_UHES) { + hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS); + printf("%s: Auto-Hibernate enter error UPMCRS=0x%x\n", + __func__, UFSHCI_REG_HCS_UPMCRS(hcs)); + } + if (status & UFSHCI_REG_IS_UHXS) { + hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS); + printf("%s: Auto-Hibernate exit error UPMCRS=0x%x\n", + __func__, UFSHCI_REG_HCS_UPMCRS(hcs)); + } if (handled == 0) { printf("%s: UNKNOWN interrupt, status=0x%08x\n", @@ -223,6 +234,12 @@ ufshci_attach(struct ufshci_softc *sc) return 1; } + /* Enable Auto-Hibernate Idle Timer (AHIT) and set it to 150ms. */ + if (sc->sc_cap & UFSHCI_REG_AUTOH8) { + UFSHCI_WRITE_4(sc, UFSHCI_REG_AHIT, + UFSHCI_REG_AHIT_TS(UFSHCI_REG_AHIT_TS_1MS) | 150); + } + /* Attach to SCSI layer */ saa.saa_adapter = &ufshci_switch; saa.saa_adapter_softc = sc; @@ -365,8 +382,14 @@ ufshci_init(struct ufshci_softc *sc) */ /* 7.1.1 Host Controller Initialization: 5) */ - UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, - UFSHCI_REG_IE_UTRCE | UFSHCI_REG_IE_UTMRCE); + if (sc->sc_cap & UFSHCI_REG_AUTOH8) { + UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, + UFSHCI_REG_IE_UTRCE | UFSHCI_REG_IE_UTMRCE | + UFSHCI_REG_IS_UHES | UFSHCI_REG_IS_UHXS); + } else { + UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, + UFSHCI_REG_IE_UTRCE | UFSHCI_REG_IE_UTMRCE); + } /* 7.1.1 Host Controller Initialization: 6) */ UFSHCI_WRITE_4(sc, UFSHCI_REG_UICCMD, diff --git a/sys/dev/ic/ufshcireg.h b/sys/dev/ic/ufshcireg.h index dfba3df69d4..b96bef52e2c 100644 --- a/sys/dev/ic/ufshcireg.h +++ b/sys/dev/ic/ufshcireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ufshcireg.h,v 1.12 2024/05/24 09:51:14 mglocker Exp $ */ +/* $OpenBSD: ufshcireg.h,v 1.13 2024/05/24 20:34:06 mglocker Exp $ */ /* * Copyright (c) 2022 Marcus Glocker @@ -56,6 +56,13 @@ #define UFSHCI_REG_HCMID_MIC(x) ((x >> 0) & 0x000000ff) /* RO */ /* Auto-Hibernate Idle Timer */ #define UFSHCI_REG_AHIT 0x18 +#define UFSHCI_REG_AHIT_TS(x) (x << 10) +#define UFSHCI_REG_AHIT_TS_1US 0x00 +#define UFSHCI_REG_AHIT_TS_10US 0x01 +#define UFSHCI_REG_AHIT_TS_100US 0x02 +#define UFSHCI_REG_AHIT_TS_1MS 0x03 +#define UFSHCI_REG_AHIT_TS_10MS 0x04 +#define UFSHCI_REG_AHIT_TS_100MS 0x05 /* * Operation and Runtime Registers -- 2.20.1