Index | Thread | Search

From:
Patrick Wildt <patrick@blueri.se>
Subject:
Qualcomm Snapdragon X Elite minimal support
To:
tech@openbsd.org
Date:
Wed, 19 Jun 2024 22:28:08 +0200

Download raw body.

Thread
Hi there,

the Qualcomm Snapdragon Elite X machines were released yesterday, I got
a Lenovo Yoga Slim 7 today, and it's already booting up with working
NVMe, USB and keyboard.  Wonder if I beat my last record.

This is focused on ACPI mode, which we will only make use of until we
can switch to device trees.  The GIC bits will require some additional
work, but hey, it's day 1.

Cheers,
Patrick

diff --git a/sys/arch/arm64/dev/agintc.c b/sys/arch/arm64/dev/agintc.c
index fbd2ec77d9d..e3e72bf24f2 100644
--- a/sys/arch/arm64/dev/agintc.c
+++ b/sys/arch/arm64/dev/agintc.c
@@ -312,6 +312,7 @@ agintc_attach(struct device *parent, struct device *self, void *aux)
 	uint32_t		 pmr, oldpmr;
 	uint32_t		 ctrl, bits;
 	uint32_t		 affinity;
+	uint64_t		 redist_stride;
 	int			 i, nbits, nintr;
 	int			 offset, nredist;
 #ifdef MULTIPROCESSOR
@@ -434,15 +435,19 @@ agintc_attach(struct device *parent, struct device *self, void *aux)
 
 	/* find the redistributors. */
 	offset = 0;
+	redist_stride = OF_getpropint64(faa->fa_node, "redistributor-stride", 0);
 	for (nredist = 0; ; nredist++) {
-		int32_t sz = (64 * 1024 * 2);
 		uint64_t typer;
+		int32_t sz;
 
 		typer = bus_space_read_8(sc->sc_iot, sc->sc_redist_base,
 		    offset + GICR_TYPER);
 
+		sz = (64 * 1024 * 2);
 		if (typer & GICR_TYPER_VLPIS)
 			sz += (64 * 1024 * 2);
+		if (redist_stride)
+			sz = redist_stride;
 
 #ifdef DEBUG_AGINTC
 		printf("probing redistributor %d %x\n", nredist, offset);
@@ -466,14 +471,17 @@ agintc_attach(struct device *parent, struct device *self, void *aux)
 	/* submap and configure the redistributors. */
 	offset = 0;
 	for (nredist = 0; nredist < sc->sc_num_redist; nredist++) {
-		int32_t sz = (64 * 1024 * 2);
 		uint64_t typer;
+		int32_t sz;
 
 		typer = bus_space_read_8(sc->sc_iot, sc->sc_redist_base,
 		    offset + GICR_TYPER);
 
+		sz = (64 * 1024 * 2);
 		if (typer & GICR_TYPER_VLPIS)
 			sz += (64 * 1024 * 2);
+		if (redist_stride)
+			sz = redist_stride;
 
 		affinity = bus_space_read_8(sc->sc_iot,
 		    sc->sc_redist_base, offset + GICR_TYPER) >> 32;
@@ -1605,6 +1613,9 @@ agintc_msi_attach(struct device *parent, struct device *self, void *aux)
 	uint64_t typer;
 	int i, hwcpu;
 
+	printf(": skipping\n");
+	return;
+
 	if (faa->fa_nreg < 1) {
 		printf(": no registers\n");
 		return;
diff --git a/sys/arch/arm64/dev/smmu_acpi.c b/sys/arch/arm64/dev/smmu_acpi.c
index b56ac927d88..105e7b68dfe 100644
--- a/sys/arch/arm64/dev/smmu_acpi.c
+++ b/sys/arch/arm64/dev/smmu_acpi.c
@@ -152,7 +152,8 @@ smmu_acpi_foundqcom(struct aml_node *node, void *arg)
 
 	if (strcmp(dev, "QCOM0409") == 0 || /* SC8180X/XP */
 	    strcmp(dev, "QCOM0609") == 0 || /* SC8280XP */
-	    strcmp(dev, "QCOM0809") == 0)   /* SC7180 */
+	    strcmp(dev, "QCOM0809") == 0 || /* SC7180 */
+	    strcmp(dev, "QCOM0C09") == 0) /* X1E80100 */
 		sc->sc_is_qcom = 1;
 
 	return 0;
diff --git a/sys/arch/arm64/stand/efiboot/efiacpi.c b/sys/arch/arm64/stand/efiboot/efiacpi.c
index 889b6f430d0..2f1d76b8339 100644
--- a/sys/arch/arm64/stand/efiboot/efiacpi.c
+++ b/sys/arch/arm64/stand/efiboot/efiacpi.c
@@ -400,6 +400,8 @@ efi_acpi_gtdt(struct acpi_table_header *hdr)
 
 static int gic_version;
 static uint64_t gicc_base;
+static uint64_t giccr_base;
+static uint64_t giccr_size;
 static uint64_t gicd_base;
 static uint64_t gicr_base;
 static uint32_t gicr_size;
@@ -436,6 +438,13 @@ efi_acpi_madt_gicc(struct acpi_madt_gicc *gicc)
 
 	/* Stash GIC information. */
 	gicc_base = gicc->base_address;
+	if (gicc->gicr_base_address) {
+		if (!giccr_base)
+			giccr_base = gicc->gicr_base_address;
+		else if (gicc->gicr_base_address)
+			giccr_base = min(giccr_base, gicc->gicr_base_address);
+		giccr_size += 0x60000;
+	}
 }
 
 void
@@ -496,7 +505,7 @@ efi_acpi_madt_gic_its(struct acpi_madt_gic_its *its)
 
 	snprintf(name, sizeof(name), "gic-its@%llx", its->base_address);
 	reg[0] = htobe64(its->base_address);
-	reg[1] = htobe64(0x20000);
+	reg[1] = htobe64(0x40000);
 	its_id = htobe32(its->gic_its_id);
 
 	/* Create "gic-its" node. */
@@ -578,8 +587,13 @@ efi_acpi_madt(struct acpi_table_header *hdr)
 		compat = "arm,gic-v3";
 		reg[0] = htobe64(gicd_base);
 		reg[1] = htobe64(0x10000);
-		reg[2] = htobe64(gicr_base);
-		reg[3] = htobe64(gicr_size);
+		if (gicr_base) {
+			reg[2] = htobe64(gicr_base);
+			reg[3] = htobe64(gicr_size);
+		} else {
+			reg[2] = htobe64(giccr_base);
+			reg[3] = htobe64(giccr_size);
+		}
 		break;
 	default:
 		return;
@@ -590,6 +604,9 @@ efi_acpi_madt(struct acpi_table_header *hdr)
 	fdt_node_set_string_property(node, "compatible", compat);
 	fdt_node_set_property(node, "reg", reg, sizeof(reg));
 	fdt_node_set_string_property(node, "status", "okay");
+
+	reg[0] = htobe64(0x40000);
+	fdt_node_add_property(node, "redistributor-stride", &reg[0], sizeof(reg[0]));
 }
 
 static int serial = 0;
diff --git a/sys/dev/acpi/qciic.c b/sys/dev/acpi/qciic.c
index 8f1eaaccc71..0295a66c6bf 100644
--- a/sys/dev/acpi/qciic.c
+++ b/sys/dev/acpi/qciic.c
@@ -107,6 +107,7 @@ int	qciic_acpi_found_ihidev(struct qciic_softc *,
 const char *qciic_hids[] = {
 	"QCOM0610",
 	"QCOM0811",
+	"QCOM0C10",
 	NULL
 };
 
diff --git a/sys/dev/acpi/xhci_acpi.c b/sys/dev/acpi/xhci_acpi.c
index a1d696e156e..4191d0efc3b 100644
--- a/sys/dev/acpi/xhci_acpi.c
+++ b/sys/dev/acpi/xhci_acpi.c
@@ -62,6 +62,9 @@ const char *xhci_hids[] = {
 	"QCOM0826",		/* SC7180 USB */
 	"QCOM24B6",		/* SDM850 URS */
 	"QCOM24B7",
+	"QCOM0C8B",		/* X1E80100 URS */
+	"QCOM0C8C",
+	"QCOM0D07",
 	NULL
 };
 
@@ -108,7 +111,10 @@ xhci_acpi_attach(struct device *parent, struct device *self, void *aux)
 	    strcmp(aaa->aaa_dev, "QCOM068B") == 0 ||
 	    strcmp(aaa->aaa_dev, "QCOM068C") == 0 ||
 	    strcmp(aaa->aaa_dev, "QCOM24B6") == 0 ||
-	    strcmp(aaa->aaa_dev, "QCOM24B7") == 0) {
+	    strcmp(aaa->aaa_dev, "QCOM24B7") == 0 ||
+	    strcmp(aaa->aaa_dev, "QCOM0C8B") == 0 ||
+	    strcmp(aaa->aaa_dev, "QCOM0C8C") == 0 ||
+	    strcmp(aaa->aaa_dev, "QCOM0D07") == 0) {
 		SIMPLEQ_FOREACH(node, &sc->sc_node->son, sib) {
 			if (strncmp(node->name, "USB", 3) == 0) {
 				aaa->aaa_node = node;