From ff605ba2eecb0d5dd640790eec6faae8836177b4 Mon Sep 17 00:00:00 2001 From: steven kao Date: Tue, 2 Jan 2018 19:07:00 -0800 Subject: [PATCH] Tegra: bpmp_ipc: support to enable/disable module clocks This patch adds support to the bpmp_ipc driver to allow clients to enable/disable clocks to hardware blocks. Currently, the API only supports SE devices. Change-Id: I9a361e380c0bcda59f5a92ca51c86a46555b2e90 Signed-off-by: steven kao --- .../tegra/common/drivers/bpmp_ipc/intf.c | 48 ++++++++++++++- .../tegra/common/drivers/bpmp_ipc/intf.h | 61 +++++++++++++++++-- plat/nvidia/tegra/include/drivers/bpmp_ipc.h | 19 +++++- 3 files changed, 122 insertions(+), 6 deletions(-) diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c index 7faa2f09e..2efa1bd98 100644 --- a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c +++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -302,3 +302,49 @@ int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id) return ret; } + +int tegra_bpmp_ipc_enable_clock(uint32_t clk_id) +{ + int ret; + struct mrq_clk_request req; + + /* only SE clocks are supported */ + if (clk_id != TEGRA_CLK_SE) { + return -ENOTSUP; + } + + /* prepare the MRQ_CLK command */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_ENABLE, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req), + NULL, 0); + if (ret != 0) { + ERROR("%s: failed for module %d with error %d\n", __func__, + clk_id, ret); + } + + return ret; +} + +int tegra_bpmp_ipc_disable_clock(uint32_t clk_id) +{ + int ret; + struct mrq_clk_request req; + + /* only SE clocks are supported */ + if (clk_id != TEGRA_CLK_SE) { + return -ENOTSUP; + } + + /* prepare the MRQ_CLK command */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_DISABLE, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req), + NULL, 0); + if (ret != 0) { + ERROR("%s: failed for module %d with error %d\n", __func__, + clk_id, ret); + } + + return ret; +} diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h index 689f8bbb8..7059c3701 100644 --- a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h +++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,10 +11,10 @@ * Flags used in IPC req */ #define FLAG_DO_ACK (U(1) << 0) -#define FLAG_RING_DOORBELL (U(1) << 1) +#define FLAG_RING_DOORBELL (U(1) << 1) /* Bit 1 is designated for CCPlex in secure world */ -#define HSP_MASTER_CCPLEX_BIT (U(1) << 1) +#define HSP_MASTER_CCPLEX_BIT (U(1) << 1) /* Bit 19 is designated for BPMP in non-secure world */ #define HSP_MASTER_BPMP_BIT (U(1) << 19) /* Timeout to receive response from BPMP is 1 sec */ @@ -49,9 +49,10 @@ struct frame_data { */ /** - * MRQ code to issue a module reset command to BPMP + * MRQ command codes */ #define MRQ_RESET U(20) +#define MRQ_CLK U(22) /** * Reset sub-commands @@ -71,4 +72,56 @@ struct __attribute__((packed)) mrq_reset_request { uint32_t reset_id; }; +/** + * MRQ_CLK sub-commands + * + */ +enum { + CMD_CLK_GET_RATE = 1, + CMD_CLK_SET_RATE = 2, + CMD_CLK_ROUND_RATE = 3, + CMD_CLK_GET_PARENT = 4, + CMD_CLK_SET_PARENT = 5, + CMD_CLK_IS_ENABLED = 6, + CMD_CLK_ENABLE = 7, + CMD_CLK_DISABLE = 8, + CMD_CLK_GET_ALL_INFO = 14, + CMD_CLK_GET_MAX_CLK_ID = 15, + CMD_CLK_MAX, +}; + +/** + * Used by the sender of an #MRQ_CLK message to control clocks. The + * clk_request is split into several sub-commands. Some sub-commands + * require no additional data. Others have a sub-command specific + * payload + * + * |sub-command |payload | + * |----------------------------|-----------------------| + * |CMD_CLK_GET_RATE |- | + * |CMD_CLK_SET_RATE |clk_set_rate | + * |CMD_CLK_ROUND_RATE |clk_round_rate | + * |CMD_CLK_GET_PARENT |- | + * |CMD_CLK_SET_PARENT |clk_set_parent | + * |CMD_CLK_IS_ENABLED |- | + * |CMD_CLK_ENABLE |- | + * |CMD_CLK_DISABLE |- | + * |CMD_CLK_GET_ALL_INFO |- | + * |CMD_CLK_GET_MAX_CLK_ID |- | + * + */ +struct mrq_clk_request { + /** + * sub-command and clock id concatenated to 32-bit word. + * - bits[31..24] is the sub-cmd. + * - bits[23..0] is the clock id + */ + uint32_t cmd_and_id; +}; + +/** + * Macro to prepare the MRQ_CLK sub-command + */ +#define make_mrq_clk_cmd(cmd, id) (((cmd) << 24) | (id & 0xFFFFFF)) + #endif /* INTF_H */ diff --git a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h index 9304150e9..d48795608 100644 --- a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h +++ b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,6 +17,11 @@ #define TEGRA_RESET_ID_XUSB_PADCTL U(114) #define TEGRA_RESET_ID_GPCDMA U(70) +/** + * Clock identifier for the SE device + */ +#define TEGRA_CLK_SE U(124) + /** * Function to initialise the IPC with the bpmp */ @@ -27,4 +32,16 @@ int32_t tegra_bpmp_ipc_init(void); */ int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id); +/** + * Handler to enable clock to a module. Only SE device is + * supported for now. + */ +int tegra_bpmp_ipc_enable_clock(uint32_t clk_id); + +/** + * Handler to disable clock to a module. Only SE device is + * supported for now. + */ +int tegra_bpmp_ipc_disable_clock(uint32_t clk_id); + #endif /* __BPMP_IPC_H__ */