1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2016 Freescale Semiconductor, Inc.
4 * Copyright 2017~2018 NXP
5 *  Author: Dong Aisheng <aisheng.dong@nxp.com>
6 *
7 * File containing client-side RPC functions for the MISC service. These
8 * function are ported to clients that communicate to the SC.
9 *
10 */
11
12#include <linux/firmware/imx/svc/misc.h>
13
14struct imx_sc_msg_req_misc_set_ctrl {
15	struct imx_sc_rpc_msg hdr;
16	u32 ctrl;
17	u32 val;
18	u16 resource;
19} __packed __aligned(4);
20
21struct imx_sc_msg_req_cpu_start {
22	struct imx_sc_rpc_msg hdr;
23	u32 address_hi;
24	u32 address_lo;
25	u16 resource;
26	u8 enable;
27} __packed __aligned(4);
28
29struct imx_sc_msg_req_misc_get_ctrl {
30	struct imx_sc_rpc_msg hdr;
31	u32 ctrl;
32	u16 resource;
33} __packed __aligned(4);
34
35struct imx_sc_msg_resp_misc_get_ctrl {
36	struct imx_sc_rpc_msg hdr;
37	u32 val;
38} __packed __aligned(4);
39
40/*
41 * This function sets a miscellaneous control value.
42 *
43 * @param[in]     ipc         IPC handle
44 * @param[in]     resource    resource the control is associated with
45 * @param[in]     ctrl        control to change
46 * @param[in]     val         value to apply to the control
47 *
48 * @return Returns 0 for success and < 0 for errors.
49 */
50
51int imx_sc_misc_set_control(struct imx_sc_ipc *ipc, u32 resource,
52			    u8 ctrl, u32 val)
53{
54	struct imx_sc_msg_req_misc_set_ctrl msg;
55	struct imx_sc_rpc_msg *hdr = &msg.hdr;
56
57	hdr->ver = IMX_SC_RPC_VERSION;
58	hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC;
59	hdr->func = (uint8_t)IMX_SC_MISC_FUNC_SET_CONTROL;
60	hdr->size = 4;
61
62	msg.ctrl = ctrl;
63	msg.val = val;
64	msg.resource = resource;
65
66	return imx_scu_call_rpc(ipc, &msg, true);
67}
68EXPORT_SYMBOL(imx_sc_misc_set_control);
69
70/*
71 * This function gets a miscellaneous control value.
72 *
73 * @param[in]     ipc         IPC handle
74 * @param[in]     resource    resource the control is associated with
75 * @param[in]     ctrl        control to get
76 * @param[out]    val         pointer to return the control value
77 *
78 * @return Returns 0 for success and < 0 for errors.
79 */
80
81int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
82			    u8 ctrl, u32 *val)
83{
84	struct imx_sc_msg_req_misc_get_ctrl msg;
85	struct imx_sc_msg_resp_misc_get_ctrl *resp;
86	struct imx_sc_rpc_msg *hdr = &msg.hdr;
87	int ret;
88
89	hdr->ver = IMX_SC_RPC_VERSION;
90	hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC;
91	hdr->func = (uint8_t)IMX_SC_MISC_FUNC_GET_CONTROL;
92	hdr->size = 3;
93
94	msg.ctrl = ctrl;
95	msg.resource = resource;
96
97	ret = imx_scu_call_rpc(ipc, &msg, true);
98	if (ret)
99		return ret;
100
101	resp = (struct imx_sc_msg_resp_misc_get_ctrl *)&msg;
102	if (val != NULL)
103		*val = resp->val;
104
105	return 0;
106}
107EXPORT_SYMBOL(imx_sc_misc_get_control);
108
109/*
110 * This function starts/stops a CPU identified by @resource
111 *
112 * @param[in]     ipc         IPC handle
113 * @param[in]     resource    resource the control is associated with
114 * @param[in]     enable      true for start, false for stop
115 * @param[in]     phys_addr   initial instruction address to be executed
116 *
117 * @return Returns 0 for success and < 0 for errors.
118 */
119int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
120			bool enable, u64 phys_addr)
121{
122	struct imx_sc_msg_req_cpu_start msg;
123	struct imx_sc_rpc_msg *hdr = &msg.hdr;
124
125	hdr->ver = IMX_SC_RPC_VERSION;
126	hdr->svc = IMX_SC_RPC_SVC_PM;
127	hdr->func = IMX_SC_PM_FUNC_CPU_START;
128	hdr->size = 4;
129
130	msg.address_hi = phys_addr >> 32;
131	msg.address_lo = phys_addr;
132	msg.resource = resource;
133	msg.enable = enable;
134
135	return imx_scu_call_rpc(ipc, &msg, true);
136}
137EXPORT_SYMBOL(imx_sc_pm_cpu_start);
138