[PATCH v3 4/5] firmware: tegra: bpmp: Add MBWT BPMP helpers
Aniruddha Rao <[email protected]>
| 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 v2: - Move the helpers near probe and document why they are needed. 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. - Add firmware error handling in the helpers. drivers/firmware/tegra/bpmp-private.h | 7 ++ drivers/firmware/tegra/bpmp.c | 109 ++++++++++++++++++++++++++ 2 files changed, 116 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 e6cf08764997..4bfd96ba9919 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -844,6 +844,115 @@ void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp) spin_unlock(&bpmp->lock); } +/* + * MBWT controls are not exposed through ordinary host MMIO and are accessed + * through BPMP firmware requests. These helpers provide the request wrappers + * used by bandwidth control callers. + */ +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) { + dev_err(bpmp->dev, "MBWT get bandwidth failed: BPMP error %d\n", + msg.rx.ret); + return -EIO; + } + + *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) { + dev_err(bpmp->dev, "MBWT set bandwidth failed: BPMP error %d\n", + msg.rx.ret); + return -EIO; + } + + return 0; +} + static int tegra_bpmp_init_channels(struct tegra_bpmp *bpmp) { size_t size; -- 2.43.0