162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2016 Freescale Semiconductor, Inc.
462306a36Sopenharmony_ci * Copyright 2017~2018 NXP
562306a36Sopenharmony_ci *  Author: Dong Aisheng <aisheng.dong@nxp.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * File containing client-side RPC functions for the MISC service. These
862306a36Sopenharmony_ci * function are ported to clients that communicate to the SC.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/firmware/imx/svc/misc.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct imx_sc_msg_req_misc_set_ctrl {
1562306a36Sopenharmony_ci	struct imx_sc_rpc_msg hdr;
1662306a36Sopenharmony_ci	u32 ctrl;
1762306a36Sopenharmony_ci	u32 val;
1862306a36Sopenharmony_ci	u16 resource;
1962306a36Sopenharmony_ci} __packed __aligned(4);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistruct imx_sc_msg_req_cpu_start {
2262306a36Sopenharmony_ci	struct imx_sc_rpc_msg hdr;
2362306a36Sopenharmony_ci	u32 address_hi;
2462306a36Sopenharmony_ci	u32 address_lo;
2562306a36Sopenharmony_ci	u16 resource;
2662306a36Sopenharmony_ci	u8 enable;
2762306a36Sopenharmony_ci} __packed __aligned(4);
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistruct imx_sc_msg_req_misc_get_ctrl {
3062306a36Sopenharmony_ci	struct imx_sc_rpc_msg hdr;
3162306a36Sopenharmony_ci	u32 ctrl;
3262306a36Sopenharmony_ci	u16 resource;
3362306a36Sopenharmony_ci} __packed __aligned(4);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct imx_sc_msg_resp_misc_get_ctrl {
3662306a36Sopenharmony_ci	struct imx_sc_rpc_msg hdr;
3762306a36Sopenharmony_ci	u32 val;
3862306a36Sopenharmony_ci} __packed __aligned(4);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/*
4162306a36Sopenharmony_ci * This function sets a miscellaneous control value.
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * @param[in]     ipc         IPC handle
4462306a36Sopenharmony_ci * @param[in]     resource    resource the control is associated with
4562306a36Sopenharmony_ci * @param[in]     ctrl        control to change
4662306a36Sopenharmony_ci * @param[in]     val         value to apply to the control
4762306a36Sopenharmony_ci *
4862306a36Sopenharmony_ci * @return Returns 0 for success and < 0 for errors.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ciint imx_sc_misc_set_control(struct imx_sc_ipc *ipc, u32 resource,
5262306a36Sopenharmony_ci			    u8 ctrl, u32 val)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	struct imx_sc_msg_req_misc_set_ctrl msg;
5562306a36Sopenharmony_ci	struct imx_sc_rpc_msg *hdr = &msg.hdr;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	hdr->ver = IMX_SC_RPC_VERSION;
5862306a36Sopenharmony_ci	hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC;
5962306a36Sopenharmony_ci	hdr->func = (uint8_t)IMX_SC_MISC_FUNC_SET_CONTROL;
6062306a36Sopenharmony_ci	hdr->size = 4;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	msg.ctrl = ctrl;
6362306a36Sopenharmony_ci	msg.val = val;
6462306a36Sopenharmony_ci	msg.resource = resource;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	return imx_scu_call_rpc(ipc, &msg, true);
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ciEXPORT_SYMBOL(imx_sc_misc_set_control);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/*
7162306a36Sopenharmony_ci * This function gets a miscellaneous control value.
7262306a36Sopenharmony_ci *
7362306a36Sopenharmony_ci * @param[in]     ipc         IPC handle
7462306a36Sopenharmony_ci * @param[in]     resource    resource the control is associated with
7562306a36Sopenharmony_ci * @param[in]     ctrl        control to get
7662306a36Sopenharmony_ci * @param[out]    val         pointer to return the control value
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci * @return Returns 0 for success and < 0 for errors.
7962306a36Sopenharmony_ci */
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciint imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
8262306a36Sopenharmony_ci			    u8 ctrl, u32 *val)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct imx_sc_msg_req_misc_get_ctrl msg;
8562306a36Sopenharmony_ci	struct imx_sc_msg_resp_misc_get_ctrl *resp;
8662306a36Sopenharmony_ci	struct imx_sc_rpc_msg *hdr = &msg.hdr;
8762306a36Sopenharmony_ci	int ret;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	hdr->ver = IMX_SC_RPC_VERSION;
9062306a36Sopenharmony_ci	hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC;
9162306a36Sopenharmony_ci	hdr->func = (uint8_t)IMX_SC_MISC_FUNC_GET_CONTROL;
9262306a36Sopenharmony_ci	hdr->size = 3;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	msg.ctrl = ctrl;
9562306a36Sopenharmony_ci	msg.resource = resource;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	ret = imx_scu_call_rpc(ipc, &msg, true);
9862306a36Sopenharmony_ci	if (ret)
9962306a36Sopenharmony_ci		return ret;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	resp = (struct imx_sc_msg_resp_misc_get_ctrl *)&msg;
10262306a36Sopenharmony_ci	if (val != NULL)
10362306a36Sopenharmony_ci		*val = resp->val;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	return 0;
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ciEXPORT_SYMBOL(imx_sc_misc_get_control);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/*
11062306a36Sopenharmony_ci * This function starts/stops a CPU identified by @resource
11162306a36Sopenharmony_ci *
11262306a36Sopenharmony_ci * @param[in]     ipc         IPC handle
11362306a36Sopenharmony_ci * @param[in]     resource    resource the control is associated with
11462306a36Sopenharmony_ci * @param[in]     enable      true for start, false for stop
11562306a36Sopenharmony_ci * @param[in]     phys_addr   initial instruction address to be executed
11662306a36Sopenharmony_ci *
11762306a36Sopenharmony_ci * @return Returns 0 for success and < 0 for errors.
11862306a36Sopenharmony_ci */
11962306a36Sopenharmony_ciint imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
12062306a36Sopenharmony_ci			bool enable, u64 phys_addr)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct imx_sc_msg_req_cpu_start msg;
12362306a36Sopenharmony_ci	struct imx_sc_rpc_msg *hdr = &msg.hdr;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	hdr->ver = IMX_SC_RPC_VERSION;
12662306a36Sopenharmony_ci	hdr->svc = IMX_SC_RPC_SVC_PM;
12762306a36Sopenharmony_ci	hdr->func = IMX_SC_PM_FUNC_CPU_START;
12862306a36Sopenharmony_ci	hdr->size = 4;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	msg.address_hi = phys_addr >> 32;
13162306a36Sopenharmony_ci	msg.address_lo = phys_addr;
13262306a36Sopenharmony_ci	msg.resource = resource;
13362306a36Sopenharmony_ci	msg.enable = enable;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	return imx_scu_call_rpc(ipc, &msg, true);
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ciEXPORT_SYMBOL(imx_sc_pm_cpu_start);
138