From nobody Tue Sep 22 13:52:53 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hq1ks6hByz6tjNc for ; Tue, 22 Sep 2026 13:52:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hq1ks5kWMz4Vw6 for ; Tue, 22 Sep 2026 13:52:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790085173; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QxydDbEaAhTeJogAq9+sAXnatLulmIvW1FlYysPh14s=; b=c7XirrzurOSXT9xNGupMoioklVMuYTWZqhgyDVb2ewyjCaddEiz6zRiZ3vzMqLqi/W3qxM fp82aqddbkFYCltYVKjC/j9f7+gUFki6BKtG5aj3YWNQY9A7F72dgolYgcIr1MY7x/3356 83Glk74R3khFSrzwgTzkdBNCQaXHtoedouDv3W7Zpt2ullbPQmiWkDaD1wYCGhUs88tHyv +AdAJl4DCscVYcmBxV96LYh9WN83Oj7TQIj5P2fcXeWmQY6wbS0IB78J6WvP+a9gee6Q6T 3xiImsHQmfODiJW/jBNSmryMerrzrwjQZnZaNEI7ywsuBoScW3od0+gQnQlaBA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1790085173; b=qcKRXJRkHz892Uq7MHWZI3cOMjkD4kPmU7Ph8Dak0beKXI+QwDKWDmM6npPX6swNVmerId 8uP/5p4t+CyV6kxjNNFFXTU68QTS1dzYtiKT/VvTu9WMGNH+sG9QTmmQ/k4zDIq0P6cQB1 taWCwpgZzYbPHL4LOy8ONjphwKMR23oiHR5Pto9ZFbSGJKpN1Mb9YaCCvXANHg++lXoRcp Lcr7icu4tZgpC0Jzp4z5dZT0xlZqnBG0dZ5Em2DbRdlrGkgBoareNV1b7eu5e9aWtSojc7 EelbttUHhallyp2z0cRAFi/rmDDatDOjFv7N3paJq36wMOsEqBY8/+UKCsdmFQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790085173; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QxydDbEaAhTeJogAq9+sAXnatLulmIvW1FlYysPh14s=; b=NMXWDy1pTZ9xdB2P+pwYBrqWLb7HdZlld/7CBtywPO0jocAu5HynrT1AWNLymBjHgWDKMJ c9VpcAmzc4pCzBoQt1hR5SGhPxKMCi7PQgiiR/jZcI/yRv3hcHmz2BaXyJI9bdWnK+cUlo OGq1U2xkjMN59DsJpiQTAogH0FG007R7zgumrhxblgxQIvF9d2i4czAa2+olqTQLVDez87 LCoA7FgxEKaQLAcpnCqPeXZVyHLWd6ulwsYgJPMm3sqPL7vAHtjuNcZi3R4tDIzTqDSIN8 fjPHMKN3gilrcTBy6APOgJmh/YKTCVHMjbWVz3q/uLYvhohc18aAsa3UCITT2A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hq1ks4mDyz18QJ for ; Tue, 22 Sep 2026 13:52:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 222cf by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 22 Sep 2026 13:52:53 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Brian Scott From: Mitchell Horne Subject: git: fa28ede31dac - main - jh7110_temp: CPU temperature sensor for JH7110 List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mhorne X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: fa28ede31dac57fdb191afd114c70439b9b41e4f Auto-Submitted: auto-generated Date: Tue, 22 Sep 2026 13:52:53 +0000 Message-Id: <6ab28835.222cf.1580fc51@gitrepo.freebsd.org> The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=fa28ede31dac57fdb191afd114c70439b9b41e4f commit fa28ede31dac57fdb191afd114c70439b9b41e4f Author: Brian Scott AuthorDate: 2026-09-22 13:31:47 +0000 Commit: Mitchell Horne CommitDate: 2026-09-22 13:52:24 +0000 jh7110_temp: CPU temperature sensor for JH7110 This patch adds a driver for the CPU temperature sensor on the jh7110 SoC. The calibration numbers come from the OpenBSD driver but are reworked to produce a result in K rather than C. The temperature is exposed as a sysctl, dev.jh7110_temp.0.temperature but I have also exposed it as dev.cpu.0.temperature because that's where you find it on a RaspberryPi and amdtemp(4), so it's a lot more obvious. (mhorne: Added 'starfive,jh7100-temp' compatible.) Reviewed by: mhorne, bnovkov MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D59478 --- sys/dev/clk/starfive/jh7110_clk_sys.c | 16 ++ sys/riscv/starfive/files.starfive | 1 + sys/riscv/starfive/jh7110_temp.c | 269 ++++++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+) diff --git a/sys/dev/clk/starfive/jh7110_clk_sys.c b/sys/dev/clk/starfive/jh7110_clk_sys.c index 4bc29b20bc91..0fbde920e250 100644 --- a/sys/dev/clk/starfive/jh7110_clk_sys.c +++ b/sys/dev/clk/starfive/jh7110_clk_sys.c @@ -49,6 +49,7 @@ static const char *cpu_core_p[] = { "cpu_root" }; static const char *cpu_bus_p[] = { "cpu_core" }; static const char *perh_root_p[] = { "pll0_out", "pll2_out" }; static const char *bus_root_p[] = { "osc", "pll2_out" }; +static const char *snd_root_p[] = { "pll2_out" }; static const char *apb_bus_p[] = { "stg_axiahb" }; static const char *apb0_p[] = { "apb_bus" }; @@ -88,6 +89,10 @@ static const char *gmac1_tx_inv_p[] = { "gmac1_tx" }; static const char *gmac1_tx_p[] = { "gmac1_gtxclk", "gmac1_rmii_rtx" }; static const char *gmac1_rx_p[] = { "gmac1_rgmii_rxin", "gmac1_rmii_rtx" }; static const char *gmac1_rx_inv_p[] = { "gmac1_rx" }; +static const char *temp_sensor_clk_apb_p[] = { "apb0" }; +static const char *temp_sensor_clk_core_p[] = { "osc" }; +static const char *pwmdac_clk_apb_p[] = { "apb0" }; +static const char *pwmdac_clk_core_p[] = { "snd_root" }; /* non-pll SYS clocks */ static const struct jh7110_clk_def sys_clks[] = { @@ -96,6 +101,7 @@ static const struct jh7110_clk_def sys_clks[] = { JH7110_DIV(JH7110_SYSCLK_CPU_BUS, "cpu_bus", cpu_bus_p, 2), JH7110_GATEDIV(JH7110_SYSCLK_PERH_ROOT, "perh_root", perh_root_p, 2), JH7110_MUX(JH7110_SYSCLK_BUS_ROOT, "bus_root", bus_root_p), + JH7110_DIV(JH7110_SYSCLK_AUDIO_ROOT, "snd_root", snd_root_p, 8), JH7110_GATE(JH7110_SYSCLK_APB0, "apb0", apb0_p), JH7110_GATE(JH7110_SYSCLK_IOMUX_APB, "u0_sys_iomux_apb", @@ -154,6 +160,16 @@ static const struct jh7110_clk_def sys_clks[] = { JH7110_GATE(JH7110_SYSCLK_GMAC1_GTXC, "gmac1_gtxc", gmac1_gtxc_p), JH7110_DIV(JH7110_SYSCLK_GMAC1_RMII_RTX, "gmac1_rmii_rtx", gmac1_rmii_rtx_p, 30), + + JH7110_GATE(JH7110_SYSCLK_TEMP_APB, "temp_sensor_clk_apb", + temp_sensor_clk_apb_p), + JH7110_GATE(JH7110_SYSCLK_TEMP_CORE, "temp_sensor_clk_core", + temp_sensor_clk_core_p), + + JH7110_GATE(JH7110_SYSCLK_PWMDAC_APB, "pwmdac_clk_apb", + pwmdac_clk_apb_p), + JH7110_GATEDIV(JH7110_SYSCLK_PWMDAC_CORE, "pwmdac_clk_core", + pwmdac_clk_core_p, 256), }; static int diff --git a/sys/riscv/starfive/files.starfive b/sys/riscv/starfive/files.starfive index 4db35e8cb351..1ecb89085ed2 100644 --- a/sys/riscv/starfive/files.starfive +++ b/sys/riscv/starfive/files.starfive @@ -11,4 +11,5 @@ dev/eqos/if_eqos_starfive.c optional eqos riscv/starfive/jh7110_gpio.c standard riscv/starfive/jh7110_pcie.c optional pci fdt +riscv/starfive/jh7110_temp.c standard riscv/starfive/starfive_syscon.c standard diff --git a/sys/riscv/starfive/jh7110_temp.c b/sys/riscv/starfive/jh7110_temp.c new file mode 100644 index 000000000000..c537f9da2e4f --- /dev/null +++ b/sys/riscv/starfive/jh7110_temp.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2022 Mark Kettenis + * Copyright (c) 2023-2024 Jari Sihvola + * Copyright (c) 2026 Brian Scott + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* Registers */ +#define TEMP 0x0000 +#define TEMP_RSTN (1 << 0) +#define TEMP_PD (1 << 1) +#define TEMP_RUN (1 << 2) +#define TEMP_DOUT_MASK 0x0fff0000 +#define TEMP_DOUT_SHIFT 16 + +/* + * These calibration numbers are based on the openbsd driver. + * + * The y intercept is -81.1C (192.05K). The slope is roughly 0.058012C/bit + * (expressed so integer arrithmetic can work). + * + * The result is in milliKelvin hence the numerator and offset being factored + * up by 1000. The 4094 looks like an error (i.e. should be 4095) but could be + * an artifact from the methods used to calculate the slope value. + */ +#define TEMP_Y_INTERCEPT 192050 +#define TEMP_SLOPE 237500 +#define TEMP_RANGE 4094 + +struct jh7110_temp_softc { + device_t dev; + struct resource *res; + struct mtx mtx; + clk_t bus; + hwreset_t rst_bus; + clk_t sense; + hwreset_t rst_sense; + struct sysctl_oid *sysctl[2]; +}; + +static struct ofw_compat_data compat_data[] = { + { "starfive,jh7100-temp", 1 }, + { "starfive,jh7110-temp", 1 }, + { NULL, 0 } +}; + +static struct resource_spec jh7110_temp_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +#define RD4(sc, reg) bus_read_4((sc)->res, (reg)) +#define WR4(sc, reg, val) bus_write_4((sc)->res, (reg), (val)) + +#define JH7110_TEMP_LOCK(_sc) mtx_lock(&(_sc)->mtx) +#define JH7110_TEMP_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) +#define JH7110_TEMP_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED) + +static int32_t +jh7110_temp_get_temperature(struct jh7110_temp_softc *sc) +{ + int32_t value; + + JH7110_TEMP_LOCK(sc); + value = RD4(sc, TEMP); + value = (value & TEMP_DOUT_MASK) >> TEMP_DOUT_SHIFT; + JH7110_TEMP_UNLOCK(sc); + + return (value * TEMP_SLOPE) / TEMP_RANGE + TEMP_Y_INTERCEPT; +} + +static int +jh7110_temperature(SYSCTL_HANDLER_ARGS) +{ + struct jh7110_temp_softc *sc = arg1; + int val; + int err; + /* get realtime value */ + val = jh7110_temp_get_temperature(sc); + + err = sysctl_handle_int(oidp, &val, 0, req); + if (err != 0 || !req->newptr) /* error || read request */ + return (err); + + return (0); +} + +static int +jh7110_temp_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "StarFive JH7110 Temperature sensor"); + + return (BUS_PROBE_DEFAULT); +} + +static int +jh7110_temp_detach(device_t dev) +{ + struct jh7110_temp_softc *sc; + + sc = device_get_softc(dev); + + bus_release_resources(dev, jh7110_temp_spec, &sc->res); + if (sc->bus != NULL) + clk_release(sc->bus); + if (sc->sense != NULL) + clk_release(sc->sense); + if (sc->rst_bus != NULL) + hwreset_release(sc->rst_bus); + if (sc->rst_sense != NULL) + hwreset_release(sc->rst_sense); + if (sc->sysctl[0] != NULL) + sysctl_remove_oid(sc->sysctl[0],1,0); + if (sc->sysctl[1] != NULL) + sysctl_remove_oid(sc->sysctl[1],1,0); + + mtx_destroy(&sc->mtx); + + return (0); +} + +static int +jh7110_temp_attach(device_t dev) +{ + struct jh7110_temp_softc *sc; + device_t cpu; + struct sysctl_ctx_list *ctx; + int rv; + + sc = device_get_softc(dev); + sc->dev = dev; + + mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); + + if ((rv = bus_alloc_resources(dev, jh7110_temp_spec, &sc->res)) != 0) { + device_printf(dev, "Could not allocate resources: %d\n", rv); + mtx_destroy(&sc->mtx); + return (ENXIO); + } + + /* Find the clocks and set them up */ + if ((rv = clk_get_by_ofw_name(dev, 0, "bus", &sc->bus)) != 0) { + device_printf(dev, "Cannot get bus clock: %d\n", rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + if ((rv = clk_enable(sc->bus)) != 0) { + device_printf(dev, "Could not enable bus clock %s: %d\n", + clk_get_name(sc->bus), rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + + if ((rv = clk_get_by_ofw_name(dev, 0, "sense", &sc->sense)) != 0) { + device_printf(dev, "Cannot get sense clock: %d\n", rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + if ((rv = clk_enable(sc->sense)) != 0) { + device_printf(dev, "Could not enable sense clock %s: %d\n", + clk_get_name(sc->sense), rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + + /* Find the clock resets and de-assert them */ + if ((rv = hwreset_get_by_ofw_name(dev, 0, "bus", &sc->rst_bus)) != 0) { + device_printf(sc->dev, "cannot get 'rst_bus' reset: %d\n", rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + if ((rv = hwreset_deassert(sc->rst_bus)) != 0) { + device_printf(sc->dev, "cannot deassert 'bus' reset: %d\n", rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + if ((rv = hwreset_get_by_ofw_name(dev, 0, "sense", + &sc->rst_sense)) != 0) { + device_printf(sc->dev, "cannot get 'rst_sense' reset: %d\n", + rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + if ((rv = hwreset_deassert(sc->rst_sense)) != 0) { + device_printf(sc->dev, "cannot deassert 'sense' reset: %d\n",rv); + jh7110_temp_detach(dev); + return (ENXIO); + } + + /* (uncritically) from the openbsd driver */ + + JH7110_TEMP_LOCK(sc); + /* Power down */ + WR4(sc, TEMP, TEMP_PD); + DELAY(1); + + /* Power up with reset asserted */ + WR4(sc, TEMP, 0); + DELAY(60); + + /* Deassert reset */ + WR4(sc, TEMP, TEMP_RSTN); + DELAY(1); + + /* Start measuring */ + WR4(sc, TEMP, TEMP_RSTN | TEMP_RUN); + JH7110_TEMP_UNLOCK(sc); + + /* add human readable temperature to dev.cpu node */ + ctx = device_get_sysctl_ctx(dev); + sc->sysctl[0] = SYSCTL_ADD_PROC(ctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "temperature", + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0, + jh7110_temperature, "IK3", + "Current SoC temperature"); + /* Make a copy where the raspberry pi puts the temperature */ + cpu = device_lookup_by_name("cpu0"); + if (cpu != NULL) { + ctx = device_get_sysctl_ctx(cpu); + sc->sysctl[1] = SYSCTL_ADD_PROC(ctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), OID_AUTO, + "temperature", + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0, + jh7110_temperature, "IK3", + "Current SoC temperature"); + } + + return (0); +} + +static device_method_t jh7110_temp_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, jh7110_temp_probe), + DEVMETHOD(device_attach, jh7110_temp_attach), + DEVMETHOD(device_detach, jh7110_temp_detach), + + DEVMETHOD_END +}; + +DEFINE_CLASS(jh7110_temp, jh7110_temp_methods, sizeof(struct jh7110_temp_softc)); +DRIVER_MODULE(jh7110_temp, simplebus, jh7110_temp_class, NULL, NULL);