From nobody Wed Oct 07 16:56:21 2026 X-Original-To: dev-commits-src-branches@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 4j0K5f26V0z6w9fx for ; Wed, 07 Oct 2026 16:56:22 +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 4j0K5d5hkWz4Wpc for ; Wed, 07 Oct 2026 16:56:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791392181; 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=DIl/ZnO+9tAk+HrQ+8JGyqOjnaoBzQXyxswL4YGWR7o=; b=A5d4sQLw0chdK4chCpfeTKiLMrK6h1jtRnx3FhYcMPU5gA4yAgZ5AE9Y1PG8TR/7y8zqw0 w77IW/1+PNMU6tuAyVfXwK5hqe8gq4hGu5+Tsji+jYCWfdSVtYrXwryc7MnWT0JLo9YZGi uB4qAehux5F7OWJxRpJK23GnHD4DGd/eV0yuAHg1mVRDR7KL/H/IRASdmXM62cXxxyvB3f yqDAzC4x1ze7iIoswSpEqH6IuXuKHCI/qhMsd4w3aK+gFiTgIzDyNIR5Ko5u1XT5gfXJHi /BDngzPT9zaOmSGoDBp+btWci4ViG20qctddXn4b/UaFlKqnbCJUlDzzhyqp/A== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791392181; b=UlI1xcg/wown2OqK2ocMaDiQNdVh3QDu++8tSybSI997Z/m5B0ZePh+XNzfu9CEV7FIGpS 5M4WS8UVQHoZ+P2muMyoWwJTIVTYV52n53qCa6vekYtRQ1j0srJ9sIb4/3LFLKvGlrEejP WOyunm+DBuPpMiJxWYL7wG1D4X5BF2itpGdf43NUS93b/tujbCUtTpTwo1cxMOaJrUv0xW joXf8mQAzBljvzTMUwiSWApqajx8pn2vLcW+sNmGfwO2rLU9ZifkDXB6ovqCNVKlUYVrWC fegSk6XXpDkYybW8qr7uO09uRJmVzNvg3XoiowmyqEw70BCFGzIzbt6e+hjCbg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791392181; 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=DIl/ZnO+9tAk+HrQ+8JGyqOjnaoBzQXyxswL4YGWR7o=; b=Cv4wavjCfNqIWgOkuMVdVS+Lp8f0i5a43VfT11pWhzeQbEYI+NNYuB0fshQ+oWopLWhps0 ZzJN/PK0ke5L7d3O46lBkrMS8BjelCqFWRlJEhSJqjbjZFnxUc33SKkZr6eKAvfHero7j1 Rw5IDd/JplB1Umea1P0Y2jpzcsZZNoczExxu9iMGxv79eirUDR643Lp7MPjwuAn8k8ioRE V8XY38tMKoxlZTURGcWLR57KJL+lGew3U960Tovx5+xZqkNWy5rPkLyiH+RVatIz3sUDHp OcsndtcPNW30bFjIz7GtjmuN4rEyqfdhkMTM6PxILcD8K+PvWjSzQVhBLj7FRQ== 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 4j0K5d35Ydz121F for ; Wed, 07 Oct 2026 16:56:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 37901 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 07 Oct 2026 16:56:21 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Brian Scott From: Mitchell Horne Subject: git: aa5fa178db14 - stable/15 - jh7110_temp: CPU temperature sensor for JH7110 List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@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/stable/15 X-Git-Reftype: branch X-Git-Commit: aa5fa178db14ca59a61df4c52ff50127a8916fa7 Auto-Submitted: auto-generated Date: Wed, 07 Oct 2026 16:56:21 +0000 Message-Id: <6ac679b5.37901.a6b91fb@gitrepo.freebsd.org> The branch stable/15 has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=aa5fa178db14ca59a61df4c52ff50127a8916fa7 commit aa5fa178db14ca59a61df4c52ff50127a8916fa7 Author: Brian Scott AuthorDate: 2026-09-22 13:31:47 +0000 Commit: Mitchell Horne CommitDate: 2026-10-07 16:55:55 +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 (cherry picked from commit fa28ede31dac57fdb191afd114c70439b9b41e4f) --- 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);