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 <[email protected]>
+ * Copyright (c) 2024 Tobias Heider <[email protected]>
*
* 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 *);