Module Name:    src
Committed By:   jmcneill
Date:           Wed Jan  8 22:58:05 UTC 2025

Modified Files:
        src/sys/dev/acpi: qcompep.c qcompep.h

Log Message:
qcompep: Add CPU frequency DVFS support.

arm64$ sysctl machdep.cpufreq
machdep.cpufreq.cpu0.target = 2976
machdep.cpufreq.cpu0.current = 2976
machdep.cpufreq.cpu0.available = 710 806 998 1190 1440 1670 1920 2188 2515 2707 
2976 3206 3417
machdep.cpufreq.cpu4.target = 3417
machdep.cpufreq.cpu4.current = 3417
machdep.cpufreq.cpu4.available = 710 806 998 1190 1440 1670 1920 2188 2515 2707 
2976 3206 3417
machdep.cpufreq.cpu8.target = 3417
machdep.cpufreq.cpu8.current = 3417
machdep.cpufreq.cpu8.available = 710 806 998 1190 1440 1670 1920 2188 2515 2707 
2976 3206 3417


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/acpi/qcompep.c \
    src/sys/dev/acpi/qcompep.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/qcompep.c
diff -u src/sys/dev/acpi/qcompep.c:1.1 src/sys/dev/acpi/qcompep.c:1.2
--- src/sys/dev/acpi/qcompep.c:1.1	Mon Dec 30 12:31:10 2024
+++ src/sys/dev/acpi/qcompep.c	Wed Jan  8 22:58:05 2025
@@ -1,7 +1,9 @@
-/* $NetBSD: qcompep.c,v 1.1 2024/12/30 12:31:10 jmcneill Exp $ */
+/* $NetBSD: qcompep.c,v 1.2 2025/01/08 22:58:05 jmcneill Exp $ */
 /*	$OpenBSD: qcaoss.c,v 1.1 2023/05/23 14:10:27 patrick Exp $	*/
+/*      $OpenBSD: qccpucp.c,v 1.1 2024/11/16 21:17:54 tobhe Exp $       */
 /*
  * Copyright (c) 2023 Patrick Wildt <patr...@blueri.se>
+ * Copyright (c) 2024 Tobias Heider <to...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -25,6 +27,8 @@
 #include <dev/acpi/qcompep.h>
 #include <dev/acpi/qcomipcc.h>
 
+#include <dev/ic/scmi.h>
+
 #define AOSS_DESC_MAGIC			0x0
 #define AOSS_DESC_VERSION		0x4
 #define AOSS_DESC_FEATURES		0x8
@@ -52,11 +56,33 @@
 #define AOSSWRITE4(sc, reg, val)					\
 	bus_space_write_4((sc)->sc_iot, (sc)->sc_aoss_ioh, (reg), (val))
 
+#define CPUCP_REG_CMD(i)	(0x104 + ((i) * 8))
+#define CPUCP_MASK_CMD		0xffffffffffffffffULL
+#define CPUCP_REG_RX_MAP	0x4000
+#define CPUCP_REG_RX_STAT	0x4400
+#define CPUCP_REG_RX_CLEAR	0x4800
+#define CPUCP_REG_RX_EN		0x4C00
+
+#define RXREAD8(sc, reg)						\
+	(bus_space_read_8((sc)->sc_iot, (sc)->sc_cpucp_rx_ioh, (reg)))
+#define RXWRITE8(sc, reg, val)						\
+	bus_space_write_8((sc)->sc_iot, (sc)->sc_cpucp_rx_ioh, (reg), (val))
+
+#define TXWRITE4(sc, reg, val)						\
+	bus_space_write_4((sc)->sc_iot, (sc)->sc_cpucp_tx_ioh, (reg), (val))
+
+
 struct qcpep_data {
 	bus_addr_t		aoss_base;
 	bus_size_t		aoss_size;
 	uint32_t		aoss_client_id;
 	uint32_t		aoss_signal_id;
+	bus_addr_t		cpucp_rx_base;
+	bus_size_t		cpucp_rx_size;
+	bus_addr_t		cpucp_tx_base;
+	bus_size_t		cpucp_tx_size;
+	bus_addr_t		cpucp_shmem_base;
+	bus_size_t		cpucp_shmem_size;
 };
 
 struct qcpep_softc {
@@ -69,6 +95,11 @@ struct qcpep_softc {
 	size_t			sc_aoss_offset;
 	size_t			sc_aoss_size;
 	void *			sc_aoss_ipcc;
+
+	bus_space_handle_t	sc_cpucp_rx_ioh;
+	bus_space_handle_t	sc_cpucp_tx_ioh;
+
+	struct scmi_softc	sc_scmi;
 };
 
 struct qcpep_softc *qcpep_sc;
@@ -78,6 +109,12 @@ static const struct qcpep_data qcpep_x1e
 	.aoss_size = 0x400,
 	.aoss_client_id = 0,	/* IPCC_CLIENT_AOP */
 	.aoss_signal_id = 0,	/* IPCC_MPROC_SIGNAL_GLINK_QMP */
+	.cpucp_rx_base = 0x17430000,
+	.cpucp_rx_size = 0x10000,
+	.cpucp_tx_base = 0x18830000,
+	.cpucp_tx_size = 0x10000,
+	.cpucp_shmem_base = 0x18b4e000,
+	.cpucp_shmem_size = 0x400,
 };
 
 static const struct device_compatible_entry compat_data[] = {
@@ -104,9 +141,12 @@ qcpep_attach(device_t parent, device_t s
 {
 	struct qcpep_softc *sc = device_private(self);
 	struct acpi_attach_args *aa = aux;
+	CPU_INFO_ITERATOR cii;
+	struct cpu_info *ci;
 	struct acpi_resources res;
+	uint8_t *scmi_shmem;
 	ACPI_STATUS rv;
-	int i;
+	int i, last_pkg;;
 
         rv = acpi_resource_parse(self, aa->aa_node->ad_handle,
 	    "_CRS", &res, &acpi_resource_parse_ops_default);
@@ -121,7 +161,19 @@ qcpep_attach(device_t parent, device_t s
 
 	if (bus_space_map(sc->sc_iot, sc->sc_data->aoss_base,
 	    sc->sc_data->aoss_size, BUS_SPACE_MAP_NONPOSTED, &sc->sc_aoss_ioh)) {
-		aprint_error_dev(self, "couldn't map registers\n");
+		aprint_error_dev(self, "couldn't map aoss registers\n");
+		return;
+	}
+	if (bus_space_map(sc->sc_iot, sc->sc_data->cpucp_rx_base,
+	    sc->sc_data->cpucp_rx_size, BUS_SPACE_MAP_NONPOSTED,
+	    &sc->sc_cpucp_rx_ioh)) {
+		aprint_error_dev(self, "couldn't map cpucp rx registers\n");
+		return;
+	}
+	if (bus_space_map(sc->sc_iot, sc->sc_data->cpucp_tx_base,
+	    sc->sc_data->cpucp_tx_size, BUS_SPACE_MAP_NONPOSTED,
+	    &sc->sc_cpucp_tx_ioh)) {
+		aprint_error_dev(self, "couldn't map cpucp tx registers\n");
 		return;
 	}
 
@@ -187,7 +239,56 @@ qcpep_attach(device_t parent, device_t s
 		return;
 	}
 
+	RXWRITE8(sc, CPUCP_REG_RX_EN, 0);
+	RXWRITE8(sc, CPUCP_REG_RX_CLEAR, 0);
+	RXWRITE8(sc, CPUCP_REG_RX_MAP, 0);
+	RXWRITE8(sc, CPUCP_REG_RX_MAP, CPUCP_MASK_CMD);
+
 	qcpep_sc = sc;
+
+	/* SCMI setup */
+	scmi_shmem = AcpiOsMapMemory(sc->sc_data->cpucp_shmem_base,
+	    sc->sc_data->cpucp_shmem_size);
+	if (scmi_shmem == NULL) {
+		aprint_error_dev(self, "couldn't map SCMI shared memory\n");
+		return;
+	}
+
+	sc->sc_scmi.sc_dev = self;
+	sc->sc_scmi.sc_iot = sc->sc_iot;
+	sc->sc_scmi.sc_shmem_tx = (struct scmi_shmem *)(scmi_shmem + 0x000);
+	sc->sc_scmi.sc_shmem_rx = (struct scmi_shmem *)(scmi_shmem + 0x200);
+	sc->sc_scmi.sc_mbox_tx = qccpucp_channel(0);
+	sc->sc_scmi.sc_mbox_tx_send = qccpucp_send;
+	sc->sc_scmi.sc_mbox_rx = qccpucp_channel(2);
+	sc->sc_scmi.sc_mbox_rx_send = qccpucp_send;
+	/* Build performance domain to CPU map. */
+	sc->sc_scmi.sc_perf_ndmap = 0;
+	last_pkg = -1;
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		if (ci->ci_package_id != last_pkg) {
+			sc->sc_scmi.sc_perf_ndmap++;
+			last_pkg = ci->ci_package_id;
+		}
+	}
+	sc->sc_scmi.sc_perf_dmap = kmem_zalloc(
+	    sizeof(*sc->sc_scmi.sc_perf_dmap) * sc->sc_scmi.sc_perf_ndmap,
+	    KM_SLEEP);
+	last_pkg = -1;
+	i = 0;
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		if (ci->ci_package_id != last_pkg) {
+			sc->sc_scmi.sc_perf_dmap[i].pm_domain = i;
+			sc->sc_scmi.sc_perf_dmap[i].pm_ci = ci;
+			last_pkg = ci->ci_package_id;
+			i++;
+		}
+	}
+	if (scmi_init_mbox(&sc->sc_scmi) != 0) {
+		aprint_error_dev(self, "couldn't setup SCMI\n");
+		return;
+	}
+	scmi_attach_perf(&sc->sc_scmi);
 }
 
 int
@@ -233,3 +334,31 @@ qcaoss_send(char *data, size_t len)
 
 	return 0;
 }
+
+void *
+qccpucp_channel(u_int id)
+{
+	struct qcpep_softc *sc = qcpep_sc;
+	uint64_t val;
+
+	if (sc == NULL || id > 2) {
+		return NULL;
+	}
+
+	val = RXREAD8(sc, CPUCP_REG_RX_EN);
+	val |= (1 << id);
+	RXWRITE8(sc, CPUCP_REG_RX_EN, val);
+	
+	return (void *)(uintptr_t)(id + 1);
+}
+
+int
+qccpucp_send(void *cookie)
+{
+	struct qcpep_softc *sc = qcpep_sc;
+	uintptr_t id = (uintptr_t)cookie - 1;
+
+	TXWRITE4(sc, CPUCP_REG_CMD(id), 0);
+	
+	return 0;
+}
Index: src/sys/dev/acpi/qcompep.h
diff -u src/sys/dev/acpi/qcompep.h:1.1 src/sys/dev/acpi/qcompep.h:1.2
--- src/sys/dev/acpi/qcompep.h:1.1	Mon Dec 30 12:31:10 2024
+++ src/sys/dev/acpi/qcompep.h	Wed Jan  8 22:58:05 2025
@@ -18,3 +18,6 @@
 #pragma once
 
 int	qcaoss_send(char *, size_t);
+
+void	*qccpucp_channel(u_int id);
+int	qccpucp_send(void *);

Reply via email to