From: Ron Manosuthi Subject: Re: Initial Raspberry Pi CPU frequency driver (apm -A) To: "tech@openbsd.org" Cc: Vitaliy Makkoveev Date: Wed, 21 Jan 2026 22:22:13 +0000 Hi Vitaliy, Diff at the end. Only changed manpage, so you can ignore it Jan :) Thanks for the feedback so far. Questions: 1. For the manpage, do I have to handle the RCS ID myself? This question also extends to code in general. 2. How are new features requiring a lot of changes handled around here? I looked through a couple commits and they follow this format: - asks "ok?" - waits - commits them upon "ok name@" but they're mostly core devs with write access to the repo, and the commits are small. Anyway, fixed all manpage lints except for mandoc: share/man/man4/man4.arm64/rpicpu.4: STYLE: RCS id missing: (OpenBSD) It looks like drivers don't really have man9, so removed reference to bcmclock_set_frequency(9). > Also. Does the `sc_post_lock' really required to be rwlock? Mutex seems > to be more reasonable here. bcmmbox_post(9) calls bcmmbox_read(9) which sleeps when !cold. Can't hold a mutex while sleeping, no? panic: assertwaitok: non-zero mutex count: 1 I could unlock it before sleeping but that would negate the whole goal of "only one post at a time". ---- re: temp > I see the temperature is much higher with your diff. Even while my RPI > does nothing and hw.perfpolicy is set to 'auto' I see the lowest > temperature is about 49 degrees. Without your diff this idling RPI is > around 42 degrees. I don't think this is an expected behavior. I see minimal temperature difference with/without the patch. It took Pi 4B a while for temperature to stabilize from unused-for-days start. I saw up to a 7C difference. Methodology: Let it rest for at least 10 minutes after boot. 22C room, no sunlight. 5 samples each. while true; do sysctl hw.sensors.bcmtmon0.temp0; sleep 60; done -- Pi 4B, small heatsink no patch hw.sensors.bcmtmon0.temp0=56.97 degC hw.sensors.bcmtmon0.temp0=56.48 degC hw.sensors.bcmtmon0.temp0=56.97 degC hw.sensors.bcmtmon0.temp0=56.48 degC hw.sensors.bcmtmon0.temp0=56.48 degC patch hw.sensors.bcmtmon0.temp0=56.48 degC hw.sensors.bcmtmon0.temp0=56.97 degC hw.sensors.bcmtmon0.temp0=56.48 degC hw.sensors.bcmtmon0.temp0=55.99 degC hw.sensors.bcmtmon0.temp0=56.48 degC -- Pi 400 no patch hw.sensors.bcmtmon0.temp0=37.97 degC hw.sensors.bcmtmon0.temp0=38.46 degC hw.sensors.bcmtmon0.temp0=37.97 degC hw.sensors.bcmtmon0.temp0=37.00 degC hw.sensors.bcmtmon0.temp0=37.48 degC patch hw.sensors.bcmtmon0.temp0=37.97 degC hw.sensors.bcmtmon0.temp0=37.97 degC hw.sensors.bcmtmon0.temp0=37.97 degC hw.sensors.bcmtmon0.temp0=38.46 degC hw.sensors.bcmtmon0.temp0=38.46 degC - Ron ---- diff --git share/man/man4/man4.arm64/Makefile share/man/man4/man4.arm64/Makefile index f85efe499e0..8de25a14a1c 100644 --- share/man/man4/man4.arm64/Makefile +++ share/man/man4/man4.arm64/Makefile @@ -6,7 +6,7 @@ MAN= agintc.4 agtimer.4 ampchwm.4 ampintc.4 \ aplhidev.4 apliic.4 aplintc.4 aplmbox.4 aplmca.4 aplnco.4 aplns.4 \ aplpcie.4 aplpinctrl.4 aplpmgr.4 aplpmu.4 aplpwm.4 \ aplsart.4 aplsmc.4 aplspi.4 aplspmi.4 apm.4 \ - intro.4 rpiclock.4 rpipwm.4 rpirtc.4 rpone.4 smbios.4 + intro.4 rpiclock.4 rpicpu.4 rpipwm.4 rpirtc.4 rpone.4 smbios.4 MANSUBDIR=arm64 diff --git share/man/man4/man4.arm64/rpicpu.4 share/man/man4/man4.arm64/rpicpu.4 new file mode 100644 index 00000000000..e90d3f88466 --- /dev/null +++ share/man/man4/man4.arm64/rpicpu.4 @@ -0,0 +1,59 @@ +.\" RCS id goes here +.\" +.\" Copyright (c) 2026 Ron Manosuthi +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: January 7 2026 $ +.Dt RPICPU 4 arm64 +.Os +.Sh NAME +.Nm rpicpu +.Nd Raspberry Pi CPU frequency driver +.Sh SYNOPSIS +.Cd "rpicpu* at fdt?" +.Sh DESCRIPTION +The +.Nm +driver enables support for CPU frequency reclocking on Raspberry Pi devices. +.Pp +Currently, the driver is only enabled for the following tested devices: +.Pp +.Bl -bullet -offset indent -compact +.It +Raspberry Pi 4B +.It +Raspberry Pi 400 +.El +.Sh SEE ALSO +.Xr bcmclock 4 , +.Xr intro 4 , +.Xr apm 8 , +.Xr apmd 8 +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 7.8 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Ron Manosuthi Aq Mt rman401@proton.me . +.Sh CAVEATS +The +.Nm +driver does not handle voltage adjustments or thermal throttling. +.Pp +Sensor reporting has not been implemented. diff --git sys/arch/arm64/conf/GENERIC sys/arch/arm64/conf/GENERIC index bc1aebe0610..100f7687744 100644 --- sys/arch/arm64/conf/GENERIC +++ sys/arch/arm64/conf/GENERIC @@ -255,6 +255,7 @@ dwctwo* at fdt? usb* at dwctwo? rpone* at pci? rpiclock* at fdt? early 1 +rpicpu* at fdt? rpigpio* at fdt? early 1 rpipwm* at fdt? rpirtc* at fdt? diff --git sys/arch/arm64/conf/files.arm64 sys/arch/arm64/conf/files.arm64 index 34d9f5d35f5..6635665cb94 100644 --- sys/arch/arm64/conf/files.arm64 +++ sys/arch/arm64/conf/files.arm64 @@ -272,6 +272,10 @@ device rpiclock attach rpiclock at fdt file arch/arm64/dev/rpiclock.c rpiclock +device rpicpu +attach rpicpu at fdt +file arch/arm64/dev/rpicpu.c rpicpu + device rpigpio attach rpigpio at fdt file arch/arm64/dev/rpigpio.c rpigpio diff --git sys/arch/arm64/dev/rpicpu.c sys/arch/arm64/dev/rpicpu.c new file mode 100644 index 00000000000..e426bdb1185 --- /dev/null +++ sys/arch/arm64/dev/rpicpu.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2026 Ron Manosuthi + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define DEVNAME(sc) ((sc)->sc_dev.dv_xname) +#define HZ_TO_MHZ(hz) ((hz) / 1000000) + +struct rpicpu_softc { + struct device sc_dev; + + uint32_t sc_min_clk_hz; + uint32_t sc_max_clk_hz; + uint32_t sc_target_clk_hz; + + struct task sc_task_reclk; +}; + +static struct rpicpu_softc *rpicpu_sc; + +int rpicpu_match(struct device *, void *, void *); +void rpicpu_attach(struct device *, struct device *, void *); +int rpicpu_get_board_rev(uint32_t *); +int rpicpu_clockspeed(int *); +void rpicpu_setperf(int); +void rpicpu_reclock(void *); + +const struct cfattach rpicpu_ca = { + sizeof (struct rpicpu_softc), rpicpu_match, rpicpu_attach +}; + +struct cfdriver rpicpu_cd = { + NULL, "rpicpu", DV_DULL +}; + +int +rpicpu_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + /* XXX find a better node */ + return OF_is_compatible(faa->fa_node, "raspberrypi,bcm2835-firmware"); +} + +void +rpicpu_attach(struct device *parent, struct device *self, void *aux) +{ + struct rpicpu_softc *sc = (struct rpicpu_softc *)self; + int error; + uint32_t board_rev; + + error = rpicpu_get_board_rev(&board_rev); + if (error) { + printf(": failed to get board revision: %d\n", error); + return; + } + board_rev &= VCPROP_REV_MODEL; + board_rev >>= 4; + if (board_rev != RPI_MODEL_4B && + board_rev != RPI_MODEL_400) { + printf(": unsupported board revision %#x\n", board_rev); + return; + } + + error = bcmclock_get_frequency(&sc->sc_min_clk_hz, + VCPROP_CLK_ARM, VCPROPTAG_GET_MIN_CLOCKRATE); + if (error) { + printf(": failed to get min clock frequency: %d\n", error); + return; + } + + error = bcmclock_get_frequency(&sc->sc_max_clk_hz, + VCPROP_CLK_ARM, VCPROPTAG_GET_MAX_CLOCKRATE); + if (error) { + printf(": failed to get max clock frequency: %d\n", error); + return; + } + + cpu_cpuspeed = rpicpu_clockspeed; + cpu_setperf = rpicpu_setperf; + + task_set(&sc->sc_task_reclk, rpicpu_reclock, sc); + rpicpu_sc = sc; + + printf(": %d-%d MHz\n", + HZ_TO_MHZ(sc->sc_min_clk_hz), + HZ_TO_MHZ(sc->sc_max_clk_hz)); + + /* XXX sensordev */ +} + +int +rpicpu_get_board_rev(uint32_t *board_rev) +{ + struct request { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_boardrev vbt_br; + struct vcprop_tag end; + } __packed; + + int error; + uint32_t result; + struct request req = { + .vb_hdr = { + .vpb_len = sizeof(req), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_br = { + .tag = { + .vpt_tag = VCPROPTAG_GET_BOARDREVISION, + .vpt_len = VCPROPTAG_LEN(req.vbt_br), + .vpt_rcode = VCPROPTAG_REQUEST + }, + .rev = 0, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL + } + }; + + error = bcmmbox_post(BCMMBOX_CHANARM2VC, &req, sizeof(req), &result); + if (error) { + printf("%s: post failed, error %d\n", __func__, error); + return error; + } + + if (vcprop_tag_success_p(&req.vbt_br.tag)) { + *board_rev = req.vbt_br.rev; + return 0; + } else { + return (EINVAL); + } +} + +int +rpicpu_clockspeed(int *freq) +{ + struct rpicpu_softc *sc = rpicpu_sc; + uint32_t clk_hz; + + if (sc == NULL) + return (ENXIO); + + clk_hz = atomic_load_int(&sc->sc_target_clk_hz); + *freq = HZ_TO_MHZ(clk_hz); + return 0; +} + +void +rpicpu_setperf(int level) +{ + struct rpicpu_softc *sc = rpicpu_sc; + uint64_t target_clk_hz, min_hz, max_hz; + + if (sc == NULL) + return; + + min_hz = sc->sc_min_clk_hz; + max_hz = sc->sc_max_clk_hz; + target_clk_hz = min_hz + (((max_hz - min_hz) * level) / 100); + atomic_store_int(&sc->sc_target_clk_hz, (uint32_t)target_clk_hz); + + /* Defer work to task queue so bcmmbox_post(9) can sleep. */ + task_add(systqmp, &sc->sc_task_reclk); +} + +void +rpicpu_reclock(void *cookie) +{ + struct rpicpu_softc *sc = (struct rpicpu_softc *)cookie; + uint32_t target_clk_hz; + + target_clk_hz = atomic_load_int(&sc->sc_target_clk_hz); + KASSERT(target_clk_hz >= sc->sc_min_clk_hz && + target_clk_hz <= sc->sc_max_clk_hz); + + bcmclock_set_frequency(VCPROP_CLK_ARM, target_clk_hz); +} diff --git sys/dev/fdt/bcm2835_clock.c sys/dev/fdt/bcm2835_clock.c index 8927f8968af..08493e30725 100644 --- sys/dev/fdt/bcm2835_clock.c +++ sys/dev/fdt/bcm2835_clock.c @@ -53,6 +53,7 @@ #include #include +#include #include #include @@ -84,14 +85,14 @@ struct bcmclock_softc { int bcmclock_match(struct device *, void *, void *); void bcmclock_attach(struct device *, struct device *, void *); +uint32_t bcmclock_cd_get_frequency(void *, uint32_t *); + const struct cfattach bcmclock_ca = { sizeof(struct bcmclock_softc), bcmclock_match, bcmclock_attach, }; -uint32_t bcmclock_get_frequency(void *, uint32_t *); - struct cfdriver bcmclock_cd = { NULL, "bcmclock", DV_DULL }; int @@ -113,21 +114,80 @@ bcmclock_attach(struct device *parent, struct device *self, void *aux) sc->sc_cd.cd_node = faa->fa_node; sc->sc_cd.cd_cookie = sc; - sc->sc_cd.cd_get_frequency = bcmclock_get_frequency; + sc->sc_cd.cd_get_frequency = bcmclock_cd_get_frequency; clock_register(&sc->sc_cd); } -uint32_t -bcmclock_get_frequency(void *cookie, uint32_t *cells) +int +bcmclock_get_frequency(uint32_t *res, uint32_t clk_vc_id, uint32_t clk_vc_type) { struct request { struct vcprop_buffer_hdr vb_hdr; struct vcprop_tag_clockrate vbt_clkrate; struct vcprop_tag end; } __packed; + uint32_t result; + int error; + + if (clk_vc_id == 0) { + printf("%s: unknown clock id %d\n", + __func__, clk_vc_id); + return (ENOENT); + } + struct request req = { + .vb_hdr = { + .vpb_len = sizeof(req), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_clkrate = { + .tag = { + .vpt_tag = clk_vc_type, + .vpt_len = VCPROPTAG_LEN(req.vbt_clkrate), + .vpt_rcode = VCPROPTAG_REQUEST + }, + .id = clk_vc_id, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL + } + }; + + error = bcmmbox_post(BCMMBOX_CHANARM2VC, &req, sizeof(req), &result); + if (error) { + printf("%s: post error %d\n", __func__, error); + return error; + } + + if (vcprop_tag_success_p(&req.vbt_clkrate.tag)) { + *res = req.vbt_clkrate.rate; + return 0; + } else { + printf("%s: vcprop result %d:%d\n", + __func__, req.vb_hdr.vpb_rcode, + req.vbt_clkrate.tag.vpt_rcode); + return (EINVAL); + } +} + +int +bcmclock_set_frequency(uint32_t clk_vc_id, uint32_t clk_hz) +{ + struct request { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_clockrate vbt_clkrate; + struct vcprop_tag end; + } __packed; uint32_t result; + int error; + + if (clk_vc_id == 0) { + printf("%s: unknown clock id %d\n", + __func__, clk_vc_id); + return (ENOENT); + } + struct request req = { .vb_hdr = { .vpb_len = sizeof(req), @@ -135,68 +195,90 @@ bcmclock_get_frequency(void *cookie, uint32_t *cells) }, .vbt_clkrate = { .tag = { - .vpt_tag = VCPROPTAG_GET_CLOCKRATE, + .vpt_tag = VCPROPTAG_SET_CLOCKRATE, .vpt_len = VCPROPTAG_LEN(req.vbt_clkrate), .vpt_rcode = VCPROPTAG_REQUEST }, + .id = clk_vc_id, + .rate = clk_hz, }, .end = { .vpt_tag = VCPROPTAG_NULL } }; + error = bcmmbox_post(BCMMBOX_CHANARM2VC, &req, sizeof(req), &result); + if (error) { + printf("%s: post error %d\n", __func__, error); + return error; + } + + if (vcprop_tag_success_p(&req.vbt_clkrate.tag)) { + return 0; + } else { + printf("%s: vcprop result %d:%d\n", + __func__, req.vb_hdr.vpb_rcode, + req.vbt_clkrate.tag.vpt_rcode); + return (EINVAL); + } +} + +uint32_t +bcmclock_cd_get_frequency(void *cookie, uint32_t *cells) +{ + uint32_t clk_id = 0; + uint32_t res; + int error; + switch (cells[0]) { case BCMCLOCK_CLOCK_TIMER: break; case BCMCLOCK_CLOCK_UART: - req.vbt_clkrate.id = VCPROP_CLK_UART; + clk_id = VCPROP_CLK_UART; break; case BCMCLOCK_CLOCK_VPU: - req.vbt_clkrate.id = VCPROP_CLK_CORE; + clk_id = VCPROP_CLK_CORE; break; case BCMCLOCK_CLOCK_V3D: - req.vbt_clkrate.id = VCPROP_CLK_V3D; + clk_id = VCPROP_CLK_V3D; break; case BCMCLOCK_CLOCK_ISP: - req.vbt_clkrate.id = VCPROP_CLK_ISP; + clk_id = VCPROP_CLK_ISP; break; case BCMCLOCK_CLOCK_H264: - req.vbt_clkrate.id = VCPROP_CLK_H264; + clk_id = VCPROP_CLK_H264; break; case BCMCLOCK_CLOCK_VEC: break; case BCMCLOCK_CLOCK_HSM: break; case BCMCLOCK_CLOCK_SDRAM: - req.vbt_clkrate.id = VCPROP_CLK_SDRAM; + clk_id = VCPROP_CLK_SDRAM; break; case BCMCLOCK_CLOCK_TSENS: break; case BCMCLOCK_CLOCK_EMMC: - req.vbt_clkrate.id = VCPROP_CLK_EMMC; + clk_id = VCPROP_CLK_EMMC; break; case BCMCLOCK_CLOCK_PERIIMAGE: break; case BCMCLOCK_CLOCK_PWM: - req.vbt_clkrate.id = VCPROP_CLK_PWM; + clk_id = VCPROP_CLK_PWM; break; case BCMCLOCK_CLOCK_PCM: break; } - - if (req.vbt_clkrate.id == 0) { - printf("bcmclock[unknown]: request to unknown clock type %d\n", - cells[0]); + if (clk_id == 0) { + printf("%s: unknown clock device %d\n", __func__, cells[0]); return 0; } - bcmmbox_post(BCMMBOX_CHANARM2VC, &req, sizeof(req), &result); - - if (vcprop_tag_success_p(&req.vbt_clkrate.tag)) - return req.vbt_clkrate.rate; - - printf("%s: vcprop result %x:%x\n", __func__, req.vb_hdr.vpb_rcode, - req.vbt_clkrate.tag.vpt_rcode); + error = bcmclock_get_frequency(&res, clk_id, VCPROPTAG_GET_CLOCKRATE); + if (error) { + printf("%s: failed to get frequency for clock device %d: \ + error %d\n", __func__, cells[0], error); + return 0; + } - return 0; + return res; } diff --git sys/dev/fdt/bcm2835_mbox.c sys/dev/fdt/bcm2835_mbox.c index 6987529f916..2835d90260a 100644 --- sys/dev/fdt/bcm2835_mbox.c +++ sys/dev/fdt/bcm2835_mbox.c @@ -76,7 +76,14 @@ struct bcmmbox_softc { void *sc_ih; - struct mutex sc_intr_lock; + /* + * We only have one DMA buffer. + * Serialize bcmmbox_post(9) to avoid overwriting it. + */ + struct rwlock sc_post_lock; + + struct mutex sc_intr_lock; + int sc_chan[BCMMBOX_NUM_CHANNELS]; uint32_t sc_mbox[BCMMBOX_NUM_CHANNELS]; }; @@ -122,6 +129,7 @@ bcmmbox_attach(struct device *parent, struct device *self, void *aux) bcmmbox_sc = sc; mtx_init(&sc->sc_intr_lock, IPL_VM); + rw_init(&sc->sc_post_lock, "bcmmbox_post"); if (faa->fa_nreg < 1) { printf(": no registers\n"); @@ -162,8 +170,8 @@ bcmmbox_attach(struct device *parent, struct device *self, void *aux) goto clean_dmamap_destroy; } - sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_VM, bcmmbox_intr, sc, - DEVNAME(sc)); + sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_VM, + bcmmbox_intr, sc, DEVNAME(sc)); if (sc->sc_ih == NULL) { printf(": failed to establish interrupt\n"); goto clean_dmamap; @@ -227,7 +235,9 @@ bcmmbox_intr_helper(struct bcmmbox_softc *sc, int broadcast) bcmmbox_reg_flush(sc, BUS_SPACE_BARRIER_READ); - while (!ISSET(bcmmbox_reg_read(sc, BCMMBOX0_STATUS), BCMMBOX_STATUS_EMPTY)) { + while (!ISSET( + bcmmbox_reg_read(sc, BCMMBOX0_STATUS), + BCMMBOX_STATUS_EMPTY)) { mbox = bcmmbox_reg_read(sc, BCMMBOX0_READ); chan = mbox & BCMMBOX_CHANNEL_MASK; @@ -318,6 +328,7 @@ bcmmbox_post(uint8_t chan, void *buf, size_t len, uint32_t *res) if (sc == NULL) return ENXIO; + rw_enter_write(&sc->sc_post_lock); memcpy(sc->sc_dmabuf, buf, len); bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, len, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -328,6 +339,7 @@ bcmmbox_post(uint8_t chan, void *buf, size_t len, uint32_t *res) bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, len, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); memcpy(buf, sc->sc_dmabuf, len); + rw_exit_write(&sc->sc_post_lock); return 0; } diff --git sys/dev/ic/bcm2835_clock.h sys/dev/ic/bcm2835_clock.h new file mode 100644 index 00000000000..f9d6d9e7ac9 --- /dev/null +++ sys/dev/ic/bcm2835_clock.h @@ -0,0 +1,7 @@ +#ifndef BCM2835_CLOCK_H +#define BCM2835_CLOCK_H + +int bcmclock_get_frequency(uint32_t *, uint32_t, uint32_t); +int bcmclock_set_frequency(uint32_t, uint32_t); + +#endif diff --git sys/dev/ic/bcm2835_vcprop.h sys/dev/ic/bcm2835_vcprop.h index 09350fc94c5..1488947ebba 100644 --- sys/dev/ic/bcm2835_vcprop.h +++ sys/dev/ic/bcm2835_vcprop.h @@ -152,27 +152,48 @@ struct vcprop_tag_boardmodel { uint32_t model; }; +/* + * Revision codes: + * + */ struct vcprop_tag_boardrev { struct vcprop_tag tag; uint32_t rev; }; #define VCPROP_REV_PCBREV 15 #define VCPROP_REV_MODEL (255 << 4) -#define RPI_MODEL_A 0 -#define RPI_MODEL_B 1 -#define RPI_MODEL_A_PLUS 2 -#define RPI_MODEL_B_PLUS 3 -#define RPI_MODEL_B_PI2 4 -#define RPI_MODEL_ALPHA 5 -#define RPI_MODEL_COMPUTE 6 -#define RPI_MODEL_ZERO 7 -#define RPI_MODEL_B_PI3 8 -#define RPI_MODEL_COMPUTE_PI3 9 -#define RPI_MODEL_ZERO_W 10 +#define RPI_MODEL_A 0x00 +#define RPI_MODEL_B 0x01 +#define RPI_MODEL_A_PLUS 0x02 +#define RPI_MODEL_B_PLUS 0x03 +#define RPI_MODEL_2B 0x04 +#define RPI_MODEL_ALPHA 0x05 +#define RPI_MODEL_CM1 0x06 +#define RPI_MODEL_3B 0x08 +#define RPI_MODEL_ZERO 0x09 +#define RPI_MODEL_CM3 0x0a +#define RPI_MODEL_ZERO_W 0x0c +#define RPI_MODEL_3B_PLUS 0x0d +#define RPI_MODEL_3A_PLUS 0x0e +/* #define RPI_MODEL_INTERNAL 0x0f */ +#define RPI_MODEL_CM3_PLUS 0x10 +#define RPI_MODEL_4B 0x11 +#define RPI_MODEL_ZERO_2W 0x12 +#define RPI_MODEL_400 0x13 +#define RPI_MODEL_CM4 0x14 +#define RPI_MODEL_CM4S 0x15 +/* #define RPI_MODEL_INTERNAL 0x16 */ +#define RPI_MODEL_5 0x17 +#define RPI_MODEL_CM5 0x18 +#define RPI_MODEL_500 0x19 +#define RPI_MODEL_CM5_LITE 0x1a + #define VCPROP_REV_PROCESSOR (15 << 12) #define RPI_PROCESSOR_BCM2835 0 #define RPI_PROCESSOR_BCM2836 1 #define RPI_PROCESSOR_BCM2837 2 +#define RPI_PROCESSOR_BCM2711 3 +#define RPI_PROCESSOR_BCM2712 4 #define VCPROP_REV_MANUF (15 << 16) #define VCPROP_REV_MEMSIZE (7 << 20) #define VCPROP_REV_ENCFLAG (1 << 23)