How to run FreeBSD on new boards built on Rockchip 35XX..


here it is
there are 4 archives kbin kernel-src and patches-main and u-boot
kbin has a prebuilt kernel and several dtb files
most are derived from the quartz64a dts (which somehow works better on my opi3b)
a.dtb is just for framebuffer / vop2 support, c.dtb has both fb and panfrost
to build the kernel binary
make -DNO_MODULES -DNOMODULES TARGET_ARCH=aarch64 TARGET=arm64 KERNCONF=GENERIC-DRM -DNO_CLEAN buildkernel
the source contains a vanilla 14.2-RELEASE + drm-subtree which sits in sys/dev/drm
drm-subtree is from https://github.com/evadot/drm-subtree
drm-subtree is patched to work on 14.2 probably 14.3 too
to see the the changes you can do git diff in sys/dev/drm
other patches to 14.2 (RK356X-diff) are from sos and this improve / add support for different rk35xx stuff
these patches are already applied, do not try to apply again
D49655.diff adds the power-domain support framework
rk_pmdomain.c is added by me (panfrost won't work without it, it will either hang or panic)

to use panfrost you need this patch to libdrm port

when porting from linux I cut out as little stuff i could so vop2 and pmdomain should work on rk35[78]x too but they have no clock and pinctrl support as of now so probably won't work in fdt mode at all (those boards have another gpu type (panthor) so panfrost won't work on them either

the whole thing is not very stable as of now there seem to be various problems with virtmem allocation / the layer that converts linux stuff to freebsd does not seem very robust
/ or i fscked something up when adjusting stuff to build on 14.2
drm-subtree has its own linuxkpi layer, it does not use the one in the maintree
there looks to be some improvements in this area in the cheribsd tree but the diff is about 12k lines, so it needs some work to be merged in

u-boot is built for opi3b
u-boot archive contents to scripts add and get to write and read the u-boot images to/from the flash card
replace da0 with your actual device before using
also the "get" script assumes a directory named "b" in the current dir where will backup current u-boot
u-boot sources comes from https://github.com/Kwiboo/u-boot-rockchip.git
i used orangepi-3b-rk3566_defconfig to which i added EFI support (CONFIG_EFI_LOADER=y)
export ROCKCHIP_TPL=rk3566_ddr_1056MHz_v1.23.bin
export BL31=rk3566/rk3568_bl31_v1.44.elf
get those from rkbin github page (the open source BL31 won't work at least for panfrost / has no scmi so no gpu clock / but this might change in the future)
 

I think that I gave you the clock patch.


I will test it soon on my Radxa Zero 3W. To which board you created and tested the code ?
 
orange pi 3b (rk3566)

but i use a slightly hacked quartz64 dtb because the opi3b has various problems.
also with edk2 i used a quartz64 one because the opi3b build bombed all the time
 
here are glmark2 results compared llvm (software) vs panfrost (hardware)
cpu was on 800mhz on both, temperature went to 80C in both.
i have no heat sink, (well i put a coin on the cpu but im not sure how much it does)

1751277436725.png
 
My god. There is no fight. What did u do to set the cpu to 800mhz ? I can only go inside the ED2K menu and select an option between low,medium,high. This is what told me Soren :

70C is on the high side, as I said earlier my two production rk356x machines runs at ~50C when not too busy and with powerd to lower clocks when not needed.
Cooling makes a huge difference, most of the solutions use thermal pads with limited abilities to transfer heat, old school good quality paste and all copper heatsinks helps quite a lot, but most important is airflow.. no airflow no cooling…

Powerd has an option to set the max frequency it allows.

If not using any frequency control you can set the start frequency from the setup menu in EDK2

He gave me a patch that I have applied,but I didn't see a decrease of the temperature. Now he wants to compare two dmesg files,before and after having applied the clock patch,to understand why his patch does not work.
 
800 is defaut u-boot sets but i can either sysctl dev.cpu.0.freq or use powerd

Did u play with the values to assign to sysctl dev.cpu.0.freq ? 80C is a lot. Didn't u find a value that has been able to decrease your high temperature value ? At 70C I have destroyed two sd cards...Can you explain how to use powerd to assign different cpu freq ?
 
it only goes to 80c when i was running the opengl benchmark
i usually don't run powerd but the board sits idle usually, i don't really used it.
i will buy a cheap alu heatsink probably
 
My Radxa Zero3E:
 
Something is misconfigured in my system after having applied the clock patch of Soren. But maybe even before to do it :

Code:
# sysctl dev.cpu.0.freq_levels
sysctl: unknown oid 'dev.cpu.0.freq_levels'

I have enabled powerd :

Code:
# ps ax | grep powerd
1218   -   I    0:00.08 /usr/local/libexec/upowerd

but :

Code:
# powerd

powerd : no cpufreq(4) support  -- aborting : no such file or directory.

# sysctl dev. | grep freq

dev.cpufreq_dt.%parent:
dev.iicbus.0.frequency: 100000

# dmesg | grep -i cpu

starting cpu 1 (100)
starting cpu 2 (200)
starting cpu 3 (300)
FreeBSD/SMP : Multiprocessor system detected : 4 CPUs
cpulist0 : open firmware cpu group on ofwbus0
cpu0 : open firmware cpu on cpulist0
cpufreq_dt0 : generic cpufreq driver on cpu0
cpufreq_dt0 : no clock for cpu@0
device_attach : cpufreq_dt0 attach returned 6
cpu 0 : arm cortex-A55 r2p0 affinity : 0 0
cpu 1 : arm cortex-A55 r2p0 affinity : 1 0
cpu 2 : arm cortex-A55 r2p0 affinity : 2 0
cpu 3 : arm cortex-A55 r2p0 affinity : 3 0
 
Between the patches of Soren,there is this one,that I have applied :

/mnt/zroot2/zroot2/OS/BSD/FreeBSD/arm64/img/Radxa-3W/Stuff/covacat/usr/src-soren-new/patches-soren/scmi.c.diff

Code:
--- trunk/stable-14/sys/dev/firmware/arm/scmi.c    2025-03-19 20:51:14.876326000 +0100
+++ branches/stable-14-deepcore/sys/dev/firmware/arm/scmi.c    2025-03-19 20:23:55.152581000 +0100
@@ -44,10 +44,15 @@
 #include <dev/ofw/ofw_bus_subr.h>
 
 #include "dev/mailbox/arm/arm_doorbell.h"
+#include "dev/psci/psci.h"
 
 #include "scmi.h"
 #include "scmi_protocols.h"
 
+enum scmi_transport {
+        SCMI_SMC = 1,
+        SCMI_MBOX,
+};
 struct scmi_softc {
     struct simplebus_softc    simplebus_sc;
     device_t        dev;
@@ -55,6 +60,8 @@
     struct arm_doorbell    *db;
     struct mtx        mtx;
     int            req_done;
+    uint32_t        smc_id;
+    uint8_t            ttype;
 };
 
 static device_t
@@ -110,7 +117,7 @@
 scmi_request_locked(struct scmi_softc *sc, struct scmi_req *req)
 {
     struct scmi_smt_header hdr;
-    int timeout;
+    int timeout, status;
 
     bzero(&hdr, sizeof(struct scmi_smt_header));
 
@@ -127,7 +134,8 @@
     hdr.msg_header = req->protocol_id << SMT_HEADER_PROTOCOL_ID_S;
     hdr.msg_header |= req->message_id << SMT_HEADER_MESSAGE_ID_S;
     hdr.length = sizeof(hdr.msg_header) + req->in_size;
-    hdr.flags |= SCMI_SHMEM_FLAG_INTR_ENABLED;
+    if (sc->ttype == SCMI_MBOX)
+        hdr.flags |= SCMI_SHMEM_FLAG_INTR_ENABLED;
 
     /* Write header */
     scmi_shmem_write(sc->tx_shmem, 0, &hdr, SMT_HEADER_SIZE);
@@ -135,32 +143,38 @@
     /* Write request */
     scmi_shmem_write(sc->tx_shmem, SMT_HEADER_SIZE, req->in_buf,
         req->in_size);
+    if (sc->ttype == SCMI_MBOX) {
 
-    sc->req_done = 0;
+        sc->req_done = 0;
 
-    /* Interrupt SCP firmware. */
-    arm_doorbell_set(sc->db);
+        /* Interrupt SCP firmware. */
+        arm_doorbell_set(sc->db);
 
-    timeout = 200;
+        timeout = 200;
 
-    dprintf("%s: request\n", __func__);
+        dprintf("%s: request\n", __func__);
 
-    do {
-        if (cold) {
-            if (arm_doorbell_get(sc->db))
-                break;
-            DELAY(10000);
-        } else {
-            msleep(sc, &sc->mtx, 0, "scmi", hz / 10);
-            if (sc->req_done)
-                break;
-        }
-    } while (timeout--);
+        do {
+            if (cold) {
+                if (arm_doorbell_get(sc->db))
+                    break;
+                DELAY(10000);
+            } else {
+                msleep(sc, &sc->mtx, 0, "scmi", hz / 10);
+                if (sc->req_done)
+                    break;
+            }
+        } while (timeout--);
 
-    if (timeout <= 0)
-        return (-1);
+        if (timeout <= 0)
+            return (-1);
 
-    dprintf("%s: got reply, timeout %d\n", __func__, timeout);
+        dprintf("%s: got reply, timeout %d\n", __func__, timeout);
+    } else {
+        status = psci_call(sc->smc_id, 0, 0, 0);
+        if (status)
+            return (status);
+    }
 
     /* Read header. */
     scmi_shmem_read(sc->tx_shmem, 0, &hdr, SMT_HEADER_SIZE);
@@ -168,7 +182,6 @@
     /* Read response */
     scmi_shmem_read(sc->tx_shmem, SMT_HEADER_SIZE, req->out_buf,
         req->out_size);
-
     return (0);
 }
 
@@ -187,13 +200,18 @@
     return (error);
 }
 
+
+static struct ofw_compat_data compat_data[] = {
+        {"arm,scmi", SCMI_MBOX},
+        {"arm,scmi-smc", SCMI_SMC},
+        {NULL,             0}
+};
 static int
 scmi_probe(device_t dev)
 {
+    if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+                return (ENXIO);
 
-    if (!ofw_bus_is_compatible(dev, "arm,scmi"))
-        return (ENXIO);
-
     if (!ofw_bus_status_okay(dev))
         return (ENXIO);
 
@@ -211,7 +229,7 @@
 
     sc = device_get_softc(dev);
     sc->dev = dev;
-
+    sc->ttype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
     node = ofw_bus_get_node(dev);
     if (node == -1)
         return (ENXIO);
@@ -222,16 +240,22 @@
         return (ENXIO);
     }
 
-    sc->db = arm_doorbell_ofw_get(sc->dev, "tx");
-    if (sc->db == NULL) {
-        device_printf(dev, "Doorbell device not found.\n");
+    if (sc->ttype == SCMI_MBOX) {
+        sc->db = arm_doorbell_ofw_get(sc->dev, "tx");
+        if (sc->db == NULL) {
+            device_printf(dev, "Doorbell device not found.\n");
+            return (ENXIO);
+        }
+
+        arm_doorbell_set_handler(sc->db, scmi_callback, sc);
+     } else {
+      if (OF_getencprop(node, "arm,smc-id", &sc->smc_id, sizeof(sc->smc_id)) <= 0) {
+        device_printf(dev, "arm,smc-id not found.\n");
         return (ENXIO);
-    }
+        }
+     }
 
     mtx_init(&sc->mtx, device_get_nameunit(dev), "SCMI", MTX_DEF);
-
-    arm_doorbell_set_handler(sc->db, scmi_callback, sc);
-
     simplebus_init(dev, node);
 
     /*
@@ -267,5 +291,5 @@
 DEFINE_CLASS_1(scmi, scmi_driver, scmi_methods, sizeof(struct scmi_softc),
     simplebus_driver);
 
-DRIVER_MODULE(scmi, simplebus, scmi_driver, 0, 0);
+EARLY_DRIVER_MODULE(scmi, simplebus, scmi_driver, 0, 0, BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_LATE);
 MODULE_VERSION(scmi, 1);
--- trunk/stable-14/sys/dev/flash/mx25l.c    2025-03-19 20:51:14.921293000 +0100
+++ branches/stable-14-deepcore/sys/dev/flash/mx25l.c    2025-03-19 20:23:55.196304000 +0100
@@ -122,6 +122,7 @@
     { "en25q64",    0x1c, 0x3017, 64 * 1024, 128, FL_ERASE_4K },
     { "m25p32",    0x20, 0x2016, 64 * 1024, 64, FL_NONE },
     { "m25p64",    0x20, 0x2017, 64 * 1024, 128, FL_NONE },
+    { "xm25qu128c",    0x20, 0x4118, 64 * 1024, 256, FL_ERASE_4K | FL_ERASE_32K },
     { "mx25l1606e", 0xc2, 0x2015, 64 * 1024, 32, FL_ERASE_4K},
     { "mx25ll32",    0xc2, 0x2016, 64 * 1024, 64, FL_NONE },
     { "mx25ll64",    0xc2, 0x2017, 64 * 1024, 128, FL_NONE },
@@ -144,6 +145,8 @@
     { "w25q64bv",    0xef, 0x4017, 64 * 1024, 128, FL_ERASE_4K },
     { "w25q128",    0xef, 0x4018, 64 * 1024, 256, FL_ERASE_4K },
     { "w25q256",    0xef, 0x4019, 64 * 1024, 512, FL_ERASE_4K },
+    { "w25q128jw",    0xef, 0x6018, 64 * 1024, 256, FL_ERASE_4K },
+    { "w25q256jw",    0xef, 0x6019, 64 * 1024, 512, FL_ERASE_4K },
 
      /* Atmel */
     { "at25df641",  0x1f, 0x4800, 64 * 1024, 128, FL_ERASE_4K },
@@ -154,6 +157,9 @@
 
     /* Integrated Silicon Solution */
     { "is25wp256",    0x9d, 0x7019, 64 * 1024, 512, FL_ERASE_4K | FL_ENABLE_4B_ADDR},
+
+    /* zbit */
+    { "zb25vq128",  0x5e, 0x4018, 64 * 1024, 256, FL_ERASE_4K },
 };
 
 static int

is it the same as your or different ? should I apply this and your or this only or your only ?

It seems that the scmi patch of Soren is not enough. Can you explain how to "set another clock for the cpu in the dtb which the default kernel can control" ? 10x
 
didn't soren give you a dtb fix ?
and i also remember seeing somewhere you can change the clock without scmi but can't find it anymore
 
If you are talking about this :

Code:
index: rk3566-radxa-zero-3.dtsi

===================================================================

--- rk3566-radxa-zero-3.dtsi    (revision 1731)

+++ rk3566-radxa-zero-3.dtsi    (working copy)

@@ -91,18 +91,22 @@

 

 &cpu0 {

        cpu-supply = <&vdd_cpu>;

+       clocks = <&cru ARMCLK>;

 };

 

 &cpu1 {

        cpu-supply = <&vdd_cpu>;

+       clocks = <&cru ARMCLK>;

 };

 

 &cpu2 {

        cpu-supply = <&vdd_cpu>;

+       clocks = <&cru ARMCLK>;

 };

 

 &cpu3 {

        cpu-supply = <&vdd_cpu>;

+       clocks = <&cru ARMCLK>;

 };

 

 &gpio0 {

yes,I've applied it. And I've got the errors that you have already seen.
 
I can't tell it now. I'm going to repeat the whole procedure of the installation of the Soren patches because I had to reinstall FreeBSD on the radxa using an old backup. That's because I swapped the kernel with another one and I kept getting the error "missing kernel" for days. Nothing is able to fix this error. Only restoring an old installation of FreeBSD,writing it again on the sd card with dd. Now,I would like to try to install your DRM patches following the instructions that you posted here :


But before to do this,I need to know if I need to reinstall all the Soren patches or if you already did it and it's enough to follow your instructions.
 
kbin has a prebuilt kernel and several dtb files

I can't use prebuilt kernels. I can't swap kernels directly. For this reason,I can't follow your instructions to the letter. Instead of using your prebuilt kernel,I need to compile a new one.
 
Soren's patches are both in the binary and the source
download 14.2 src.txz and unpack it on your x86 box somewhere
replace the new usr/src/sys with whats on gdrive source
use the make command above
you can
make -DNO_MODULES -DNOMODULES TARGET_ARCH=aarch64 TARGET=arm64 KERNCONF=GENERIC-DRM DESTDIR=/somewhere/else installkernel
the installkernel command needs to be run as root so don't forget DESTDIR
run it without root first and make sure it fails on the correct destdir
you don't want an arm kernel installed on your x86 box

make -DNO_MODULES -DNOMODULES TARGET_ARCH=aarch64 TARGET=arm64 KERNCONF=GENERIC-DRM DESTDIR=/home/titus/k installkernel
....
...

install -p -m 444 -o root -g wheel kernel /home/titus/k/boot/kernel/
install: /home/titus/k/boot/kernel/kernel: chown/chgrp: Operation not permitted

remove the NOMODULES NO_MODULES stuff to get the full stuff built and installed
 
I've understood when the error "can't find kernel" comes out. When I rename the "kernel" file located on /boot/kernel with a different name,for example "kernel-old" and then I copy a different "kernel" file in the same directory. In other words,I can only replace/overwrite the "kernel" file in loco. Is there an explanation for this ?
 
it shouldn't
i just scp my kernel from the devbox to the board over and over without problems

Probably you overwrite the old kernel version with a new one. I imagine that u never renamed the old one (to keep it stored there) and copied a new kernel with the name "kernel". Don't do it :D
 
Anyway,you claimed that the DRM driver that you ported from Linux on the Rockchip 35XX is not stable. Some time ago JSM told me that also the panfrost driver for the RK3399 is not stable,but only with 4 GB of ram. I imagine that it needs more RAM. Also an excessive overheating may cause instability.

Passive cooling with FreeBSD is not enough to reach and keep a cpu temperature of 50 C. So,I will try this new active heat sink :

https://it.aliexpress.com/item/1005003651858159.html

So I bought a new radxa zero 3W with 8 GB of RAM and the gpio pin header expansion pre soldered to power on the new heatsink.

I think that I will have the optimal situation to stress your panfrost implementation.
 
i hacked in the drm-subtree version from cheribsd which is a bit better and it does not crash as bad (no more locks or panics)
still panfrost fails at times to allocate contiguous memory and i have to reboot to fix it
we need iommu for rockchip vops and then integrated in drm and with panfrost which looks rather complex
 
i hacked in the drm-subtree version from cheribsd which is a bit better and it does not crash as bad (no more locks or panics)
still panfrost fails at times to allocate contiguous memory and i have to reboot to fix it
we need iommu for rockchip vops and then integrated in drm and with panfrost which looks rather complex

This could be a project for the next user who writes to the FreeBSD ML asking how his skills can be useful. Maybe this project can be assigned to someone for the new GSOC...At least,some part of the job...
 
Back
Top