On Mon, Jun 15, 2026 at 08:37:30AM +0000, Aniruddha Rao wrote: > Add helper functions that send MBWT requests to BPMP firmware on > Tegra410. > > The helpers implement the GET_BW and SET_BW operations and provide a > QUERY_ABI-based probe for command availability. I'd rather not make this Tegra410 specific. We might need it on future chips, too. In fact, given the size, I'd be inclined to just include this unconditionally in the BPMP driver. > Signed-off-by: Aniruddha Rao > --- > drivers/firmware/tegra/Makefile | 1 + > drivers/firmware/tegra/bpmp-private.h | 31 +++++++ > drivers/firmware/tegra/bpmp-tegra410.c | 108 +++++++++++++++++++++++++ > 3 files changed, 140 insertions(+) > create mode 100644 drivers/firmware/tegra/bpmp-tegra410.c > > diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile > index 41e2e4dc31d6..4310cc0ff294 100644 > --- a/drivers/firmware/tegra/Makefile > +++ b/drivers/firmware/tegra/Makefile > @@ -4,6 +4,7 @@ tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC) += bpmp-tegra210.o > tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC) += bpmp-tegra186.o > tegra-bpmp-$(CONFIG_ARCH_TEGRA_194_SOC) += bpmp-tegra186.o > tegra-bpmp-$(CONFIG_ARCH_TEGRA_234_SOC) += bpmp-tegra186.o > +tegra-bpmp-$(CONFIG_ARCH_TEGRA_410_SOC) += bpmp-tegra410.o Just make this bpmp-mbwt.o or maybe even stick it into bpmp.c. It's barely 100 lines of proper code. > tegra-bpmp-$(CONFIG_ARCH_TEGRA_264_SOC) += bpmp-tegra186.o > tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o > obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o > diff --git a/drivers/firmware/tegra/bpmp-private.h b/drivers/firmware/tegra/bpmp-private.h > index ebde0e36ae20..c3f466ae5979 100644 > --- a/drivers/firmware/tegra/bpmp-private.h > +++ b/drivers/firmware/tegra/bpmp-private.h > @@ -35,4 +35,35 @@ struct tegra_bpmp_acpi_message { > u8 data[TEGRA_BPMP_ACPI_BMRQ_DATA_SZ]; > }; > > +#if IS_ENABLED(CONFIG_ARCH_TEGRA_410_SOC) > +int tegra410_bpmp_mbwt_set(struct tegra_bpmp *bpmp, unsigned int instance, > + unsigned int vc_type, unsigned int bandwidth); > +int tegra410_bpmp_mbwt_get(struct tegra_bpmp *bpmp, unsigned int instance, > + unsigned int vc_type, unsigned int *bandwidth_out); > +bool tegra410_bpmp_mbwt_cmd_is_supported(struct tegra_bpmp *bpmp, > + unsigned int cmd_code); > +#else > +static inline int tegra410_bpmp_mbwt_set(struct tegra_bpmp *bpmp, > + unsigned int instance, > + unsigned int vc_type, > + unsigned int bandwidth) > +{ > + return -EOPNOTSUPP; > +} > + > +static inline int tegra410_bpmp_mbwt_get(struct tegra_bpmp *bpmp, > + unsigned int instance, > + unsigned int vc_type, > + unsigned int *bandwidth_out) > +{ > + return -EOPNOTSUPP; > +} > + > +static inline bool tegra410_bpmp_mbwt_cmd_is_supported(struct tegra_bpmp *bpmp, > + unsigned int cmd_code) > +{ > + return false; > +} > +#endif We can then drop the 410 from the prefix and get rid of the dummy implementations. Thierry > + > #endif > diff --git a/drivers/firmware/tegra/bpmp-tegra410.c b/drivers/firmware/tegra/bpmp-tegra410.c > new file mode 100644 > index 000000000000..87c5dfab864b > --- /dev/null > +++ b/drivers/firmware/tegra/bpmp-tegra410.c > @@ -0,0 +1,108 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) 2026, NVIDIA CORPORATION. > + */ > + > +#include > +#include > +#include > + > +#include > +#include > + > +#include "bpmp-private.h" > + > +bool tegra410_bpmp_mbwt_cmd_is_supported(struct tegra_bpmp *bpmp, > + unsigned int cmd_code) > +{ > + struct mrq_sochub_mbwt_request request; > + struct tegra_bpmp_message msg; > + int err; > + > + memset(&request, 0, sizeof(request)); > + request.cmd = CMD_SOCHUB_MBWT_QUERY_ABI; > + request.query_abi.cmd_code = cmd_code; > + > + memset(&msg, 0, sizeof(msg)); > + msg.mrq = MRQ_SOCHUB_MBWT; > + msg.tx.data = &request; > + msg.tx.size = sizeof(request); > + > + err = tegra_bpmp_transfer(bpmp, &msg); > + if (err || msg.rx.ret) > + return false; > + > + return true; > +} > + > +int tegra410_bpmp_mbwt_set(struct tegra_bpmp *bpmp, > + unsigned int instance, > + unsigned int vc_type, > + unsigned int bandwidth) > +{ > + struct mrq_sochub_mbwt_request request; > + struct tegra_bpmp_message msg; > + int err; > + > + memset(&request, 0, sizeof(request)); > + request.cmd = CMD_SOCHUB_MBWT_SET_BW; > + request.set_bw.instance = instance; > + request.set_bw.vc_type = vc_type; > + request.set_bw.bw = bandwidth; > + > + memset(&msg, 0, sizeof(msg)); > + msg.mrq = MRQ_SOCHUB_MBWT; > + msg.tx.data = &request; > + msg.tx.size = sizeof(request); > + > + err = tegra_bpmp_transfer(bpmp, &msg); > + > + if (err) { > + dev_err(bpmp->dev, "MBWT set bandwidth transfer failed: %d\n", err); > + return err; > + } > + if (msg.rx.ret < 0) > + return msg.rx.ret; > + > + return 0; > +} > + > +int tegra410_bpmp_mbwt_get(struct tegra_bpmp *bpmp, > + unsigned int instance, > + unsigned int vc_type, > + unsigned int *bandwidth_out) > +{ > + struct mrq_sochub_mbwt_request request; > + struct mrq_sochub_mbwt_response response; > + struct tegra_bpmp_message msg; > + int err; > + > + if (!bandwidth_out) > + return -EINVAL; > + > + memset(&request, 0, sizeof(request)); > + request.cmd = CMD_SOCHUB_MBWT_GET_BW; > + request.get_bw.instance = instance; > + request.get_bw.vc_type = vc_type; > + > + memset(&response, 0, sizeof(response)); > + > + memset(&msg, 0, sizeof(msg)); > + msg.mrq = MRQ_SOCHUB_MBWT; > + msg.tx.data = &request; > + msg.tx.size = sizeof(request); > + msg.rx.data = &response; > + msg.rx.size = sizeof(response); > + > + err = tegra_bpmp_transfer(bpmp, &msg); > + if (err) { > + dev_err(bpmp->dev, "MBWT get bandwidth transfer failed: %d\n", err); > + return err; > + } > + if (msg.rx.ret < 0) > + return msg.rx.ret; > + > + *bandwidth_out = response.get_bw.bw; > + > + return 0; > +} > -- > 2.43.0 >