Enable UFS "Auto-Hibernation". From the documentation:
authormglocker <mglocker@openbsd.org>
Fri, 24 May 2024 20:34:06 +0000 (20:34 +0000)
committermglocker <mglocker@openbsd.org>
Fri, 24 May 2024 20:34:06 +0000 (20:34 +0000)
Auto-hibernate allows the host controller to put UniPro link into Hibernate
state autonomously.

sys/dev/ic/ufshci.c
sys/dev/ic/ufshcireg.h

index 7b04d3e..cf969e4 100644 (file)
@@ -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 <mglocker@openbsd.org>
@@ -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,
index dfba3df..b96bef5 100644 (file)
@@ -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 <mglocker@openbsd.org>
 #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