summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/arm64/dev/smmu.c21
-rw-r--r--sys/arch/arm64/dev/smmureg.h7
-rw-r--r--sys/arch/arm64/dev/smmuvar.h7
3 files changed, 29 insertions, 6 deletions
diff --git a/sys/arch/arm64/dev/smmu.c b/sys/arch/arm64/dev/smmu.c
index e8f103add8c..37b6d79ee5d 100644
--- a/sys/arch/arm64/dev/smmu.c
+++ b/sys/arch/arm64/dev/smmu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smmu.c,v 1.19 2022/08/10 17:02:37 patrick Exp $ */
+/* $OpenBSD: smmu.c,v 1.20 2022/09/11 10:18:54 patrick Exp $ */
/*
* Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com>
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
@@ -260,6 +260,8 @@ smmu_attach(struct smmu_softc *sc)
*/
sc->sc_cb[sc->sc_num_context_banks - 1] =
malloc(sizeof(struct smmu_cb), M_DEVBUF, M_WAITOK | M_ZERO);
+ smmu_cb_write_4(sc, sc->sc_num_context_banks - 1,
+ SMMU_CB_SCTLR, 0);
smmu_gr1_write_4(sc, SMMU_CBAR(sc->sc_num_context_banks - 1),
SMMU_CBAR_TYPE_S1_TRANS_S2_BYPASS);
}
@@ -272,8 +274,13 @@ smmu_attach(struct smmu_softc *sc)
/* On QCOM HW we need to keep current streams running. */
if (sc->sc_is_qcom && sc->sc_smr &&
smmu_gr0_read_4(sc, SMMU_SMR(i)) & SMMU_SMR_VALID) {
+ reg = smmu_gr0_read_4(sc, SMMU_SMR(i));
sc->sc_smr[i] = malloc(sizeof(struct smmu_smr),
M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->sc_smr[i]->ss_id = (reg >> SMMU_SMR_ID_SHIFT) &
+ SMMU_SMR_ID_MASK;
+ sc->sc_smr[i]->ss_mask = (reg >> SMMU_SMR_MASK_SHIFT) &
+ SMMU_SMR_MASK_MASK;
if (sc->sc_bypass_quirk) {
smmu_gr0_write_4(sc, SMMU_S2CR(i),
SMMU_S2CR_TYPE_TRANS |
@@ -603,10 +610,22 @@ smmu_domain_create(struct smmu_softc *sc, uint32_t sid)
/* Stream mapping is a bit more effort */
if (sc->sc_smr) {
for (i = 0; i < sc->sc_num_streams; i++) {
+ /* Take over QCOM SMRs */
+ if (sc->sc_is_qcom && sc->sc_smr[i] != NULL &&
+ sc->sc_smr[i]->ss_dom == NULL &&
+ sc->sc_smr[i]->ss_id == sid &&
+ sc->sc_smr[i]->ss_mask == 0) {
+ free(sc->sc_smr[i], M_DEVBUF,
+ sizeof(struct smmu_smr));
+ sc->sc_smr[i] = NULL;
+ }
if (sc->sc_smr[i] != NULL)
continue;
sc->sc_smr[i] = malloc(sizeof(struct smmu_smr),
M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->sc_smr[i]->ss_dom = dom;
+ sc->sc_smr[i]->ss_id = sid;
+ sc->sc_smr[i]->ss_mask = 0;
dom->sd_smr_idx = i;
break;
}
diff --git a/sys/arch/arm64/dev/smmureg.h b/sys/arch/arm64/dev/smmureg.h
index 926d2d9ae8b..3b1962f021b 100644
--- a/sys/arch/arm64/dev/smmureg.h
+++ b/sys/arch/arm64/dev/smmureg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smmureg.h,v 1.1 2021/02/28 21:39:31 patrick Exp $ */
+/* $OpenBSD: smmureg.h,v 1.2 2022/09/11 10:18:54 patrick Exp $ */
/*
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
*
@@ -122,8 +122,11 @@
#define SMMU_STLBGSTATUS 0x074
#define SMMU_STLBGSTATUS_GSACTIVE (1 << 0)
#define SMMU_SMR(x) (0x800 + (x) * 0x4) /* 0 - 127 */
+#define SMMU_SMR_ID_SHIFT 0
+#define SMMU_SMR_ID_MASK 0x7fff
+#define SMMU_SMR_MASK_SHIFT 16
+#define SMMU_SMR_MASK_MASK 0x7fff
#define SMMU_SMR_VALID (1U << 31)
-#define SMMU_SMR_MASK (0x7fff << 16)
#define SMMU_S2CR(x) (0xc00 + (x) * 0x4) /* 0 - 127 */
#define SMMU_S2CR_EXIDVALID (1 << 10)
#define SMMU_S2CR_TYPE_TRANS (0 << 16)
diff --git a/sys/arch/arm64/dev/smmuvar.h b/sys/arch/arm64/dev/smmuvar.h
index e7d97fddc4d..c01e10518ee 100644
--- a/sys/arch/arm64/dev/smmuvar.h
+++ b/sys/arch/arm64/dev/smmuvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smmuvar.h,v 1.7 2022/08/10 17:02:37 patrick Exp $ */
+/* $OpenBSD: smmuvar.h,v 1.8 2022/09/11 10:18:54 patrick Exp $ */
/*
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
*
@@ -44,8 +44,9 @@ struct smmu_cb_irq {
};
struct smmu_smr {
- uint16_t mask;
- uint16_t id;
+ struct smmu_domain *ss_dom;
+ uint16_t ss_id;
+ uint16_t ss_mask;
};
struct smmu_softc {