Add support for suspend/resume.
authormglocker <mglocker@openbsd.org>
Fri, 24 May 2024 09:51:13 +0000 (09:51 +0000)
committermglocker <mglocker@openbsd.org>
Fri, 24 May 2024 09:51:13 +0000 (09:51 +0000)
ok dlg@

sys/dev/ic/ufshci.c
sys/dev/ic/ufshcireg.h
sys/dev/ic/ufshcivar.h
sys/dev/pci/ufshci_pci.c

index b52ab3c..7b04d3e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ufshci.c,v 1.30 2024/05/22 11:46:06 mglocker Exp $ */
+/*     $OpenBSD: ufshci.c,v 1.31 2024/05/24 09:51:14 mglocker Exp $ */
 
 /*
  * Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
@@ -79,6 +79,8 @@ int                    ufshci_utr_cmd_sync(struct ufshci_softc *,
                             struct ufshci_ccb *, struct scsi_xfer *,
                             uint32_t, uint16_t);
 int                     ufshci_xfer_complete(struct ufshci_softc *);
+int                     ufshci_powerdown(struct ufshci_softc *);
+int                     ufshci_resume(struct ufshci_softc *);
 
 /* SCSI */
 int                     ufshci_ccb_alloc(struct ufshci_softc *, int);
@@ -1317,6 +1319,81 @@ ufshci_xfer_complete(struct ufshci_softc *sc)
        return 0;
 }
 
+int
+ufshci_activate(struct ufshci_softc *sc, int act)
+{
+       int rv = 0;
+
+       switch (act) {
+       case DVACT_POWERDOWN:
+               DPRINTF(1, "%s: POWERDOWN\n", __func__);
+               rv = config_activate_children(&sc->sc_dev, act);
+               ufshci_powerdown(sc);
+               break;
+       case DVACT_RESUME:
+               DPRINTF(1, "%s: RESUME\n", __func__);
+               ufshci_resume(sc);
+               if (rv == 0)
+                       rv = config_activate_children(&sc->sc_dev, act);
+               break;
+       default:
+               rv = config_activate_children(&sc->sc_dev, act);
+               break;
+       }
+
+       return rv;
+}
+
+int
+ufshci_powerdown(struct ufshci_softc *sc)
+{
+       uint32_t reg;
+
+       /* Send "hibernate enter" command. */
+       UFSHCI_WRITE_4(sc, UFSHCI_REG_UICCMD,
+           UFSHCI_REG_UICCMD_CMDOP_DME_HIBERNATE_ENTER);
+       if (ufshci_is_poll(sc, UFSHCI_REG_IS_UHES) != 0) {
+               printf("%s: hibernate enter cmd failed\n", __func__);
+               return 1;
+       }
+
+       /* Check if "hibernate enter" command was executed successfully. */
+       reg = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
+       DPRINTF(1, "%s: UPMCRS=0x%x\n", __func__, UFSHCI_REG_HCS_UPMCRS(reg));
+       if (UFSHCI_REG_HCS_UPMCRS(reg) > UFSHCI_REG_HCS_UPMCRS_PWR_REMTOTE) {
+               printf("%s: hibernate enter cmd returned UPMCRS error=0x%x\n",
+                   __func__, UFSHCI_REG_HCS_UPMCRS(reg));
+               return 1;
+       }
+
+       return 0;
+}
+
+int
+ufshci_resume(struct ufshci_softc *sc)
+{
+       uint32_t reg;
+
+       /* Send "hibernate exit" command. */
+       UFSHCI_WRITE_4(sc, UFSHCI_REG_UICCMD,
+           UFSHCI_REG_UICCMD_CMDOP_DME_HIBERNATE_EXIT);
+       if (ufshci_is_poll(sc, UFSHCI_REG_IS_UHXS) != 0) {
+               printf("%s: hibernate exit command failed\n", __func__);
+               return 1;
+       }
+
+       /* Check if "hibernate exit" command was executed successfully. */
+       reg = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
+       DPRINTF(1, "%s: UPMCRS=0x%x\n", __func__, UFSHCI_REG_HCS_UPMCRS(reg));
+       if (UFSHCI_REG_HCS_UPMCRS(reg) > UFSHCI_REG_HCS_UPMCRS_PWR_REMTOTE) {
+               printf("%s: hibernate exit cmd returned UPMCRS error=0x%x\n",
+                   __func__, UFSHCI_REG_HCS_UPMCRS(reg));
+               return 1;
+       }
+
+       return 0;
+}
+
 /* SCSI */
 
 int
index 702b604..dfba3df 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ufshcireg.h,v 1.11 2024/05/22 18:10:00 mglocker Exp $ */
+/*     $OpenBSD: ufshcireg.h,v 1.12 2024/05/24 09:51:14 mglocker Exp $ */
 
 /*
  * Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
 #define  UFSHCI_REG_HCS_TTAGUTPE(x)    ((x >> 16) & 0x000000ff) /* RO */
 #define  UFSHCI_REG_HCS_UTPEC(x)       ((x >> 12) & 0x0000000f) /* RO */
 #define  UFSHCI_REG_HCS_UPMCRS(x)      ((x >>  8) & 0x00000007) /* RO */
+#define   UFSHCI_REG_HCS_UPMCRS_PWR_OK         0x00
+#define   UFSHCI_REG_HCS_UPMCRS_PWR_LOCAL      0x01
+#define   UFSHCI_REG_HCS_UPMCRS_PWR_REMTOTE    0x02
+#define   UFSHCI_REG_HCS_UMPCRS_PWR_BUSY       0x03
+#define   UFSHCI_REG_HCS_UMPCRS_PWR_ERROR_CAP  0x04
+#define   UFSHCI_REG_HCS_UMPCRS_PWR_FATAL_ERROR        0x05
 #define  UFSHCI_REG_HCS_UCRDY          (1 << 3) /* RO */
 #define  UFSHCI_REG_HCS_UTMRLRDY       (1 << 2) /* RO */
 #define  UFSHCI_REG_HCS_UTRLRDY                (1 << 1) /* RO */
index 81e5bb2..b2e15e6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ufshcivar.h,v 1.7 2024/05/20 12:42:45 mglocker Exp $ */
+/*     $OpenBSD: ufshcivar.h,v 1.8 2024/05/24 09:51:14 mglocker Exp $ */
 
 /*
  * Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
@@ -84,3 +84,4 @@ struct ufshci_softc {
 int    ufshci_intr(void *);
 void   ufshci_attach_hook(struct device *);    /* XXX: Only for testing */
 int    ufshci_attach(struct ufshci_softc *);
+int    ufshci_activate(struct ufshci_softc *, int);
index c94cf14..f265d20 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ufshci_pci.c,v 1.3 2024/05/13 01:15:51 jsg Exp $ */
+/*     $OpenBSD: ufshci_pci.c,v 1.4 2024/05/24 09:51:13 mglocker Exp $ */
 
 /*
  * Copyright (c) 2024 Marcus Glocker <mglocker@openbsd.org>
@@ -41,12 +41,14 @@ struct ufshci_pci_softc {
 int    ufshci_pci_match(struct device *, void *, void *);
 void   ufshci_pci_attach(struct device *, struct device *, void *);
 int    ufshci_pci_detach(struct device *, int);
+int    ufshci_pci_activate(struct device *, int);
 
 const struct cfattach ufshci_pci_ca = {
        sizeof(struct ufshci_pci_softc),
        ufshci_pci_match,
        ufshci_pci_attach,
-       ufshci_pci_detach
+       ufshci_pci_detach,
+       ufshci_pci_activate
 };
 
 int
@@ -106,3 +108,11 @@ ufshci_pci_detach(struct device *self, int flags)
 {
        return 0;
 }
+
+int
+ufshci_pci_activate(struct device *self, int act)
+{
+       struct ufshci_pci_softc *psc = (struct ufshci_pci_softc *)self;
+
+       return ufshci_activate(&psc->psc_ufshci, act);
+}