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 *);