Hello,

This series adds support for RISC-V Platform Management Interface (RPMI) to
U-Boot. RPMI is an OS-agnostic protocol for communication between an
Application Processor (AP) and a Platform Microcontroller (PuC) [1]. There
are some similarities between RPMI and SCMI.

This patchset first adds an abstraction layer for the transport
(UCLASS_RPMI), then adds two transport layer (SBI MPXY and shared memory)
and finally adds one client (or service group in RPMI jargon): the clock
service group.

This series also includes a sandbox mode for which the RPMI transport
doesn't attach to a firmware but contains a simulation of a firmware. This
reuses code from librpmi [2] to create the message responses.

>From V3, this series also includes the "mpxy" command line tool created
by Rahul [6].

Apart from the spec [1], this series reuses code from the Linux SBI MPXY
driver [3], OpenSBI shared memory transport [4] and Linux RPMI clock driver
[5].

This was tested on a PIC64-HPSC SoC which features an application cluster and a
system controller with isolated address spaces, hence the need for RPMI. This
series can also be tested with QEMU using the steps detailed in the following
section.

# Testing

## Build qemu

Build QEMU using Subrahmanya Lingappa v11 patches [7] that adds support for
librpmi along with another patch (by me) that adds some phony clocks for
testing. This is available at [8] for your convenience. You will also need to
download and build librpmi since it is a dependency of qemu, any recent version
should do. The following commands do all of this:

````
git clone https://github.com/riscv-software-src/librpmi.git
cd librpmi
make
make install I=install
sed -i "s|\${prefix}|$(pwd)/install|g" ./install/lib/pkgconfig/librpmi.pc
export PKG_CONFIG_PATH="$(pwd)/install/lib/pkgconfig:$PKG_CONFIG_PATH"
cd ..
git clone https://github.com/ch-perry/qemu.git -b rpmi_patches_with_clocks
cd qemu
./configure --enable-librpmi
make -j8 qemu-system-riscv32 qemu-system-riscv64
export PATH="$(pwd)/build:$PATH"
````

## Device tree

We also need to tweak a bit the device tree used by QEMU. This is done
externally because we need to append a different fragment depending on if we're
testing M mode U-Boot or S Mode U-Boot.

For M mode U-Boot, we use:

```
cat <<EOF > overlay-mmode.dts
/ {
        clock-controller {
                #clock-cells = <1>;
                mboxes = <&{/soc/mailbox@10200000} 0x08>;
                compatible = "riscv,rpmi-clock";
        };
};
EOF
```

While for S mode, we use:

```
cat <<EOF > overlay-smode.dts
/ {
        clock-controller {
                #clock-cells = <1>;
                mboxes = <&mbox 0x1000 0x00>;
                compatible = "riscv,rpmi-clock";
        };

        mbox: mailbox {
                #mbox-cells = <2>;
                compatible = "riscv,sbi-mpxy-mbox";
        };
};
EOF
```

## Test RV64 in M mode:

Source your RV64 compiler, build U-Boot's qemu-riscv64_defconfig and test with
QEMU:

```
make clean
make qemu-riscv64_defconfig && echo CONFIG_CMD_CLK=y >> .config
make -j8
qemu-system-riscv64 -cpu rv64 -smp 4 -M virt,rpmi=on,dumpdtb=qemu.dtb
dtc -O dts qemu.dtb | cat - ./overlay-mmode.dts | dtc -o qemu_mmode.dtb -I dts -
qemu-system-riscv64 -cpu rv64 -smp 4 -M virt,rpmi=on -dtb qemu_mmode.dtb 
-nographic -bios u-boot.bin
```

`clk dump` should report 2 clocks.

## Test RV64 in S mode:

Build any recent version of OpenSBI using the generic platform and the default
defconfig:

```
git clone https://github.com/riscv-software-src/opensbi.git
cd opensbi
make PLATFORM=generic
cp build/platform/generic/firmware/fw_dynamic.bin ../u-boot/fw_dynamic_rv64.bin
cd ../u-boot
```

Back in U-Boot, build qemu-riscv64_smode_defconfig and test with QEMU:

```
make clean
make qemu-riscv64_smode_defconfig && echo CONFIG_CMD_CLK=y >> .config
make -j8
qemu-system-riscv64 -cpu rv64 -smp 4 -M virt,rpmi=on,dumpdtb=qemu.dtb
dtc -O dts qemu.dtb | cat - ./overlay-smode.dts | dtc -o qemu_smode.dtb -I dts -
qemu-system-riscv64 -cpu rv64 -smp 4 -M virt,rpmi=on \
    -dtb qemu_smode.dtb -nographic \
    -bios fw_dynamic_rv64.bin \
    -kernel u-boot.bin
```

`clk dump` should report 2 clocks. You can also use the `mpxy` command.

## Test RV32 in M mode:

Source your RV32 compiler, build U-Boot's qemu-riscv32_defconfig and test with
QEMU:

```
make clean
make qemu-riscv32_defconfig && echo CONFIG_CMD_CLK=y >> .config
make -j8
qemu-system-riscv32 -cpu rv32 -smp 4 -M virt,rpmi=on,dumpdtb=qemu.dtb
dtc -O dts qemu.dtb | cat - ./overlay-mmode.dts | dtc -o qemu_mmode.dtb -I dts -
qemu-system-riscv32 -cpu rv32 -smp 4 -M virt,rpmi=on -dtb qemu_mmode.dtb 
-nographic -bios u-boot.bin
```

`clk dump` should report 2 clocks.

## Test RV32 in S mode:

Build OpenSBI for 32 bits, the instructions are the same as for 64 bits but with
an rv32 toolchain in CROSS_COMPILE. Build U-Boot's qemu-riscv32_smode_defconfig
and test with QEMU:

```
make clean
make qemu-riscv32_smode_defconfig && echo CONFIG_CMD_CLK=y >> .config
make -j8
qemu-system-riscv32 -cpu rv32 -smp 4 -M virt,rpmi=on,dumpdtb=qemu.dtb
dtc -O dts qemu.dtb | cat - ./overlay-smode.dts | dtc -o qemu_smode.dtb -I dts -
qemu-system-riscv32 -cpu rv32 -smp 4 -M virt,rpmi=on \
    -dtb qemu_smode.dtb -nographic \
    -bios fw_dynamic_rv32.bin \
    -kernel u-boot.bin
```

`clk dump` should report 2 clocks. You can also use the `mpxy` command.

# References

[1]: https://github.com/riscv-non-isa/riscv-rpmi
[2]: https://github.com/riscv-software-src/librpmi
[3]: 
https://elixir.bootlin.com/linux/v7.0.10/source/drivers/mailbox/riscv-sbi-mpxy-mbox.c
[4]: 
https://elixir.bootlin.com/opensbi/v1.8.1/source/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
[5]: https://elixir.bootlin.com/linux/v7.0.10/source/drivers/clk/clk-rpmi.c
[6]: 
https://lore.kernel.org/all/[email protected]/
[7]: 
https://lore.kernel.org/all/[email protected]/
[8]: https://github.com/ch-perry/qemu/commits/rpmi_patches_with_clocks/

# Changelog

Changes in v4:
 - I forgot to send patch 1 in v3, add it back.
 - Add patches 7 and 8 that add the relevant RPMI defconfig to
   qemu-riscv[32|64]_smode_defconfig and qemu-riscv[32|64]_defconfig
 - Add instructions on how to test on QEMU in the cover letter
 - Fix the default value of the doorbell from 0 to 1 in the MPXY driver
 - Force a device_probe() of all UCLASS_RPMI devices if g_mpxy is NULL in the 
mpxy command
 - Remove the unnecessary edit to "cmd/riscv/Makefile" (mpxy command)

Changes in v3:
 - Added the "mpxy" command from Rahul. See [6].

Changes in v2:
 - Drop the device-power service group as the DT bindings for it are not
   mainlined (was patch 5 and 7).
 - Reorder headers in all .c files.
 - Don't null check pointers before free().
 - Improve error messages in rpmi_check_versions() (patch 1).
 - Remove struct sbi_mpxy_rpmi_channel_attrs and struct
   sbi_mpxy_channel_attrs for simpler u32 arrays (patch 2).
 - Remove transition_latency from struct rpmi_clk_def as it's unused (patch 4).
 - Simplify last return path of _rpmi_clk_enable_disable() (patch 4).
 - Move the call to _rpmi_clk_get_rate() from _rpmi_clk_set_rate() to
   rpmi_clk_set_rate() (patch 4).

Signed-off-by: Charles Perry <[email protected]>
---
Charles Perry (7):
      firmware: add support for RPMI
      firmware: rpmi: add support for the SBI MPXY transport
      firmware: rpmi: add support for shared memory transport
      drivers: clk: add support for RPMI clocks
      firmware: rpmi: add a test and a sandbox driver
      configs: qemu-riscv[32|64]_smode_defconfig: add RPMI configs
      configs: qemu-riscv[32|64]_defconfig: add RPMI configs

Rahul Pathak (1):
      drivers: firmware: rpmi: Add the mpxy command

 MAINTAINERS                                |   8 +
 arch/riscv/include/asm/sbi.h               |  57 ++
 arch/sandbox/dts/test.dts                  |  12 +
 configs/qemu-riscv32_defconfig             |   3 +
 configs/qemu-riscv32_smode_defconfig       |   4 +
 configs/qemu-riscv64_defconfig             |   3 +
 configs/qemu-riscv64_smode_defconfig       |   4 +
 configs/sandbox_defconfig                  |   2 +
 drivers/clk/Kconfig                        |   7 +
 drivers/clk/Makefile                       |   1 +
 drivers/clk/clk_rpmi.c                     | 344 ++++++++++++
 drivers/firmware/Kconfig                   |   1 +
 drivers/firmware/Makefile                  |   1 +
 drivers/firmware/rpmi/Kconfig              |  34 ++
 drivers/firmware/rpmi/Makefile             |   4 +
 drivers/firmware/rpmi/rpmi-sandbox-clock.c | 446 ++++++++++++++++
 drivers/firmware/rpmi/rpmi-sandbox.c       | 156 ++++++
 drivers/firmware/rpmi/rpmi-sandbox.h       |  47 ++
 drivers/firmware/rpmi/rpmi-sbi-mpxy.c      | 806 +++++++++++++++++++++++++++++
 drivers/firmware/rpmi/rpmi-shmem.c         | 473 +++++++++++++++++
 drivers/firmware/rpmi/rpmi-uclass.c        | 144 ++++++
 include/dm/uclass-id.h                     |   1 +
 include/rpmi-uclass.h                      |  79 +++
 include/rpmi.h                             | 159 ++++++
 include/rpmi_proto.h                       | 125 +++++
 test/dm/Makefile                           |   1 +
 test/dm/rpmi.c                             |  48 ++
 27 files changed, 2970 insertions(+)
---
base-commit: fed92546960a92177d67c0b8d7b22385f50fed29
change-id: 20261012-rpmi_v4-811f5d688cbc

Best regards,
-- 
Charles Perry <[email protected]>

Reply via email to