[PATCH v2 4/5] firmware: tegra: bpmp: Add MBWT BPMP helpers
Aniruddha Rao <[email protected]> Wed, 22 Jul 2026 11:05:43 +0000
| Newsgroups | org.kernel.vger.linux-tegra,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add helper functions that send MBWT requests to BPMP firmware. The helpers implement the GET_BW and SET_BW operations. They also provide a QUERY_ABI-based probe for command availability. Signed-off-by: Aniruddha Rao <[email protected]> --- Changes since v1: - Use generic tegra_bpmp_mbwt_*() helper names. - Fold the helpers into bpmp.c instead of adding a separate source file. - Drop SoC-specific Kconfig dependencies from the helper patch. - Return BPMP firmware errors directly. drivers/firmware/tegra/bpmp-private.h | 7 ++ drivers/firmware/tegra/bpmp.c | 98 +++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/drivers/firmware/tegra/bpmp-private.h b/drivers/firmware/tegra/bpmp-private.h index 07c3d46abb87..b3770e71020e 100644 --- a/drivers/firmware/tegra/bpmp-private.h +++ b/drivers/firmware/tegra/bpmp-private.h @@ -26,4 +26,11 @@ struct tegra_bpmp_ops { extern const struct tegra_bpmp_ops tegra186_bpmp_ops; extern const struct tegra_bpmp_ops tegra210_bpmp_ops; +bool tegra_bpmp_mbwt_cmd_is_supported(struct tegra_bpmp *bpmp, + unsigned int cmd_code); +int tegra_bpmp_mbwt_get(struct tegra_bpmp *bpmp, unsigned int instance, + unsigned int vc_type, unsigned int *bandwidth); +int tegra_bpmp_mbwt_set(struct tegra_bpmp *bpmp, unsigned int instance, + unsigned int vc_type, unsigned int bandwidth); + #endif diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 2dcb74a45b59..2cf8490b8b2e 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -675,6 +675,104 @@ bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp, unsigned int mrq) } EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_is_supported); +bool tegra_bpmp_mbwt_cmd_is_supported(struct tegra_bpmp *bpmp, + unsigned int cmd_code) +{ + struct mrq_sochub_mbwt_request request = { + .cmd = CMD_SOCHUB_MBWT_QUERY_ABI, + .query_abi.cmd_code = cmd_code, + }; + struct tegra_bpmp_message msg = { + .mrq = MRQ_SOCHUB_MBWT, + .tx = { + .data = &request, + .size = sizeof(request), + }, + }; + int err; + + err = tegra_bpmp_transfer(bpmp, &msg); + if (err || msg.rx.ret) + return false; + + return true; +} + +int tegra_bpmp_mbwt_get(struct tegra_bpmp *bpmp, unsigned int instance, + unsigned int vc_type, unsigned int *bandwidth) +{ + struct mrq_sochub_mbwt_request request = { + .cmd = CMD_SOCHUB_MBWT_GET_BW, + .get_bw = { + .instance = instance, + .vc_type = vc_type, + }, + }; + struct mrq_sochub_mbwt_response response = {}; + struct tegra_bpmp_message msg = { + .mrq = MRQ_SOCHUB_MBWT, + .tx = { + .data = &request, + .size = sizeof(request), + }, + .rx = { + .data = &response, + .size = sizeof(response), + }, + }; + int err; + + if (!bandwidth) + return -EINVAL; + + 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) + return msg.rx.ret; + + *bandwidth = response.get_bw.bw; + + return 0; +} + +int tegra_bpmp_mbwt_set(struct tegra_bpmp *bpmp, unsigned int instance, + unsigned int vc_type, unsigned int bandwidth) +{ + struct mrq_sochub_mbwt_request request = { + .cmd = CMD_SOCHUB_MBWT_SET_BW, + .set_bw = { + .instance = instance, + .vc_type = vc_type, + .bw = bandwidth, + }, + }; + struct tegra_bpmp_message msg = { + .mrq = MRQ_SOCHUB_MBWT, + .tx = { + .data = &request, + .size = sizeof(request), + }, + }; + int err; + + 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) + return msg.rx.ret; + + return 0; +} + static void tegra_bpmp_mrq_handle_ping(unsigned int mrq, struct tegra_bpmp_channel *channel, void *data) -- 2.43.0