| // SPDX-License-Identifier: GPL-2.0+ | 
 | /* | 
 |  * Copyright (C) 2016 Freescale Semiconductor, Inc. | 
 |  * Copyright 2017~2018 NXP | 
 |  *  Author: Dong Aisheng <aisheng.dong@nxp.com> | 
 |  * | 
 |  * File containing client-side RPC functions for the MISC service. These | 
 |  * function are ported to clients that communicate to the SC. | 
 |  * | 
 |  */ | 
 |  | 
 | #include <linux/firmware/imx/svc/misc.h> | 
 |  | 
 | struct imx_sc_msg_req_misc_set_ctrl { | 
 | 	struct imx_sc_rpc_msg hdr; | 
 | 	u32 ctrl; | 
 | 	u32 val; | 
 | 	u16 resource; | 
 | } __packed __aligned(4); | 
 |  | 
 | struct imx_sc_msg_req_cpu_start { | 
 | 	struct imx_sc_rpc_msg hdr; | 
 | 	u32 address_hi; | 
 | 	u32 address_lo; | 
 | 	u16 resource; | 
 | 	u8 enable; | 
 | } __packed __aligned(4); | 
 |  | 
 | struct imx_sc_msg_req_misc_get_ctrl { | 
 | 	struct imx_sc_rpc_msg hdr; | 
 | 	u32 ctrl; | 
 | 	u16 resource; | 
 | } __packed __aligned(4); | 
 |  | 
 | struct imx_sc_msg_resp_misc_get_ctrl { | 
 | 	struct imx_sc_rpc_msg hdr; | 
 | 	u32 val; | 
 | } __packed __aligned(4); | 
 |  | 
 | /* | 
 |  * This function sets a miscellaneous control value. | 
 |  * | 
 |  * @param[in]     ipc         IPC handle | 
 |  * @param[in]     resource    resource the control is associated with | 
 |  * @param[in]     ctrl        control to change | 
 |  * @param[in]     val         value to apply to the control | 
 |  * | 
 |  * @return Returns 0 for success and < 0 for errors. | 
 |  */ | 
 |  | 
 | int imx_sc_misc_set_control(struct imx_sc_ipc *ipc, u32 resource, | 
 | 			    u8 ctrl, u32 val) | 
 | { | 
 | 	struct imx_sc_msg_req_misc_set_ctrl msg; | 
 | 	struct imx_sc_rpc_msg *hdr = &msg.hdr; | 
 |  | 
 | 	hdr->ver = IMX_SC_RPC_VERSION; | 
 | 	hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC; | 
 | 	hdr->func = (uint8_t)IMX_SC_MISC_FUNC_SET_CONTROL; | 
 | 	hdr->size = 4; | 
 |  | 
 | 	msg.ctrl = ctrl; | 
 | 	msg.val = val; | 
 | 	msg.resource = resource; | 
 |  | 
 | 	return imx_scu_call_rpc(ipc, &msg, true); | 
 | } | 
 | EXPORT_SYMBOL(imx_sc_misc_set_control); | 
 |  | 
 | /* | 
 |  * This function gets a miscellaneous control value. | 
 |  * | 
 |  * @param[in]     ipc         IPC handle | 
 |  * @param[in]     resource    resource the control is associated with | 
 |  * @param[in]     ctrl        control to get | 
 |  * @param[out]    val         pointer to return the control value | 
 |  * | 
 |  * @return Returns 0 for success and < 0 for errors. | 
 |  */ | 
 |  | 
 | int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource, | 
 | 			    u8 ctrl, u32 *val) | 
 | { | 
 | 	struct imx_sc_msg_req_misc_get_ctrl msg; | 
 | 	struct imx_sc_msg_resp_misc_get_ctrl *resp; | 
 | 	struct imx_sc_rpc_msg *hdr = &msg.hdr; | 
 | 	int ret; | 
 |  | 
 | 	hdr->ver = IMX_SC_RPC_VERSION; | 
 | 	hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC; | 
 | 	hdr->func = (uint8_t)IMX_SC_MISC_FUNC_GET_CONTROL; | 
 | 	hdr->size = 3; | 
 |  | 
 | 	msg.ctrl = ctrl; | 
 | 	msg.resource = resource; | 
 |  | 
 | 	ret = imx_scu_call_rpc(ipc, &msg, true); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	resp = (struct imx_sc_msg_resp_misc_get_ctrl *)&msg; | 
 | 	if (val != NULL) | 
 | 		*val = resp->val; | 
 |  | 
 | 	return 0; | 
 | } | 
 | EXPORT_SYMBOL(imx_sc_misc_get_control); | 
 |  | 
 | /* | 
 |  * This function starts/stops a CPU identified by @resource | 
 |  * | 
 |  * @param[in]     ipc         IPC handle | 
 |  * @param[in]     resource    resource the control is associated with | 
 |  * @param[in]     enable      true for start, false for stop | 
 |  * @param[in]     phys_addr   initial instruction address to be executed | 
 |  * | 
 |  * @return Returns 0 for success and < 0 for errors. | 
 |  */ | 
 | int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource, | 
 | 			bool enable, u64 phys_addr) | 
 | { | 
 | 	struct imx_sc_msg_req_cpu_start msg; | 
 | 	struct imx_sc_rpc_msg *hdr = &msg.hdr; | 
 |  | 
 | 	hdr->ver = IMX_SC_RPC_VERSION; | 
 | 	hdr->svc = IMX_SC_RPC_SVC_PM; | 
 | 	hdr->func = IMX_SC_PM_FUNC_CPU_START; | 
 | 	hdr->size = 4; | 
 |  | 
 | 	msg.address_hi = phys_addr >> 32; | 
 | 	msg.address_lo = phys_addr; | 
 | 	msg.resource = resource; | 
 | 	msg.enable = enable; | 
 |  | 
 | 	return imx_scu_call_rpc(ipc, &msg, true); | 
 | } | 
 | EXPORT_SYMBOL(imx_sc_pm_cpu_start); |