blob: 000a31f1b7b1df118582611e093f3d6a944c4322 [file] [log] [blame]
Peng Fan55486382018-10-18 14:28:12 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2018 NXP
4 *
5 * Peng Fan <peng.fan@nxp.com>
6 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <dm.h>
11#include <asm/arch/sci/sci.h>
12#include <misc.h>
13
14DECLARE_GLOBAL_DATA_PTR;
15
16/* CLK and PM */
17int sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk,
18 sc_pm_clock_rate_t *rate)
19{
20 struct udevice *dev = gd->arch.scu_dev;
21 int size = sizeof(struct sc_rpc_msg_s);
22 struct sc_rpc_msg_s msg;
23 int ret;
24
25 RPC_VER(&msg) = SC_RPC_VERSION;
26 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM;
27 RPC_FUNC(&msg) = (u8)PM_FUNC_SET_CLOCK_RATE;
28 RPC_U32(&msg, 0U) = *(u32 *)rate;
29 RPC_U16(&msg, 4U) = (u16)resource;
30 RPC_U8(&msg, 6U) = (u8)clk;
31 RPC_SIZE(&msg) = 3U;
32
33 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
34 if (ret)
35 printf("%s: rate:%u resource:%u: clk:%u res:%d\n",
36 __func__, *rate, resource, clk, RPC_R8(&msg));
37
38 *rate = RPC_U32(&msg, 0U);
39
40 return ret;
41}
42
43int sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk,
44 sc_pm_clock_rate_t *rate)
45{
46 struct udevice *dev = gd->arch.scu_dev;
47 int size = sizeof(struct sc_rpc_msg_s);
48 struct sc_rpc_msg_s msg;
49 int ret;
50
51 RPC_VER(&msg) = SC_RPC_VERSION;
52 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM;
53 RPC_FUNC(&msg) = (u8)PM_FUNC_GET_CLOCK_RATE;
54 RPC_U16(&msg, 0U) = (u16)resource;
55 RPC_U8(&msg, 2U) = (u8)clk;
56 RPC_SIZE(&msg) = 2U;
57
58 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
59 if (ret) {
60 printf("%s: resource:%d clk:%d: res:%d\n",
61 __func__, resource, clk, RPC_R8(&msg));
62 return ret;
63 }
64
65 if (rate)
66 *rate = RPC_U32(&msg, 0U);
67
68 return 0;
69}
70
71int sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk,
72 sc_bool_t enable, sc_bool_t autog)
73{
74 struct udevice *dev = gd->arch.scu_dev;
75 int size = sizeof(struct sc_rpc_msg_s);
76 struct sc_rpc_msg_s msg;
77 int ret;
78
79 RPC_VER(&msg) = SC_RPC_VERSION;
80 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM;
81 RPC_FUNC(&msg) = (u8)PM_FUNC_CLOCK_ENABLE;
82 RPC_U16(&msg, 0U) = (u16)resource;
83 RPC_U8(&msg, 2U) = (u8)clk;
84 RPC_U8(&msg, 3U) = (u8)enable;
85 RPC_U8(&msg, 4U) = (u8)autog;
86 RPC_SIZE(&msg) = 3U;
87
88 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
89 if (ret)
90 printf("%s: resource:%d clk:%d: enable:%d autog: %d, res:%d\n",
91 __func__, resource, clk, enable, autog, RPC_R8(&msg));
92
93 return ret;
94}
95
96int sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
97 sc_pm_power_mode_t mode)
98{
99 struct udevice *dev = gd->arch.scu_dev;
100 int size = sizeof(struct sc_rpc_msg_s);
101 struct sc_rpc_msg_s msg;
102 int ret;
103
104 if (!dev)
105 hang();
106
107 RPC_VER(&msg) = SC_RPC_VERSION;
108 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM;
109 RPC_FUNC(&msg) = (u8)PM_FUNC_SET_RESOURCE_POWER_MODE;
110 RPC_U16(&msg, 0U) = (u16)resource;
111 RPC_U8(&msg, 2U) = (u8)mode;
112 RPC_SIZE(&msg) = 2U;
113
114 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
115 if (ret)
116 printf("%s: resource:%d mode:%d: res:%d\n",
117 __func__, resource, mode, RPC_R8(&msg));
118
119 return ret;
120}
121
Peng Fan098d3e62019-08-26 08:12:16 +0000122sc_bool_t sc_pm_is_partition_started(sc_ipc_t ipc, sc_rm_pt_t pt)
123{
124 struct udevice *dev = gd->arch.scu_dev;
125 int size = sizeof(struct sc_rpc_msg_s);
126 struct sc_rpc_msg_s msg;
127 int ret;
128 u8 result;
129
130 RPC_VER(&msg) = SC_RPC_VERSION;
131 RPC_SVC(&msg) = (u8)(SC_RPC_SVC_PM);
132 RPC_FUNC(&msg) = (u8)(PM_FUNC_IS_PARTITION_STARTED);
133 RPC_U8(&msg, 0U) = (u8)(pt);
134 RPC_SIZE(&msg) = 2U;
135
136 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
137
138 result = RPC_R8(&msg);
139 if (result != 0 && result != 1) {
140 printf("%s: partition:%d res:%d\n",
141 __func__, pt, RPC_R8(&msg));
142 if (ret)
143 printf("%s: partition:%d res:%d\n", __func__, pt,
144 RPC_R8(&msg));
145 }
146 return !!result;
147}
148
Peng Fan55486382018-10-18 14:28:12 +0200149/* PAD */
150int sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, u32 val)
151{
152 struct udevice *dev = gd->arch.scu_dev;
153 int size = sizeof(struct sc_rpc_msg_s);
154 struct sc_rpc_msg_s msg;
155 int ret;
156
157 if (!dev)
158 hang();
159
160 RPC_VER(&msg) = SC_RPC_VERSION;
161 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PAD;
162 RPC_FUNC(&msg) = (u8)PAD_FUNC_SET;
163 RPC_U32(&msg, 0U) = (u32)val;
164 RPC_U16(&msg, 4U) = (u16)pad;
165 RPC_SIZE(&msg) = 3U;
166
167 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
168 if (ret)
169 printf("%s: val:%d pad:%d: res:%d\n",
170 __func__, val, pad, RPC_R8(&msg));
171
172 return ret;
173}
174
175/* MISC */
176int sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource, sc_ctrl_t ctrl,
177 u32 *val)
178{
179 struct udevice *dev = gd->arch.scu_dev;
180 int size = sizeof(struct sc_rpc_msg_s);
181 struct sc_rpc_msg_s msg;
182 int ret;
183
184 if (!dev)
185 hang();
186
187 RPC_VER(&msg) = SC_RPC_VERSION;
188 RPC_SVC(&msg) = (u8)SC_RPC_SVC_MISC;
189 RPC_FUNC(&msg) = (u8)MISC_FUNC_GET_CONTROL;
190 RPC_U32(&msg, 0U) = (u32)ctrl;
191 RPC_U16(&msg, 4U) = (u16)resource;
192 RPC_SIZE(&msg) = 3U;
193
194 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
195 if (ret)
196 printf("%s: ctrl:%d resource:%d: res:%d\n",
197 __func__, ctrl, resource, RPC_R8(&msg));
198
Peng Fan927a3dc2018-12-15 12:19:49 +0000199 if (val)
Peng Fan55486382018-10-18 14:28:12 +0200200 *val = RPC_U32(&msg, 0U);
201
202 return ret;
203}
204
205void sc_misc_get_boot_dev(sc_ipc_t ipc, sc_rsrc_t *boot_dev)
206{
207 struct udevice *dev = gd->arch.scu_dev;
208 int size = sizeof(struct sc_rpc_msg_s);
209 struct sc_rpc_msg_s msg;
210 int ret;
211
212 if (!dev)
213 hang();
214
215 RPC_VER(&msg) = SC_RPC_VERSION;
216 RPC_SVC(&msg) = (u8)SC_RPC_SVC_MISC;
217 RPC_FUNC(&msg) = (u8)MISC_FUNC_GET_BOOT_DEV;
218 RPC_SIZE(&msg) = 1U;
219
220 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
221 if (ret)
222 printf("%s: res:%d\n", __func__, RPC_R8(&msg));
223
Peng Fan927a3dc2018-12-15 12:19:49 +0000224 if (boot_dev)
Peng Fan55486382018-10-18 14:28:12 +0200225 *boot_dev = RPC_U16(&msg, 0U);
226}
227
228void sc_misc_boot_status(sc_ipc_t ipc, sc_misc_boot_status_t status)
229{
230 struct udevice *dev = gd->arch.scu_dev;
231 int size = sizeof(struct sc_rpc_msg_s);
232 struct sc_rpc_msg_s msg;
233 int ret;
234
235 if (!dev)
236 hang();
237
238 RPC_VER(&msg) = SC_RPC_VERSION;
239 RPC_SVC(&msg) = (u8)SC_RPC_SVC_MISC;
240 RPC_FUNC(&msg) = (u8)MISC_FUNC_BOOT_STATUS;
241 RPC_U8(&msg, 0U) = (u8)status;
242 RPC_SIZE(&msg) = 2U;
243
244 ret = misc_call(dev, SC_TRUE, &msg, size, &msg, size);
245 if (ret)
246 printf("%s: status:%d res:%d\n",
247 __func__, status, RPC_R8(&msg));
248}
249
250void sc_misc_build_info(sc_ipc_t ipc, u32 *build, u32 *commit)
251{
252 struct udevice *dev = gd->arch.scu_dev;
253 int size = sizeof(struct sc_rpc_msg_s);
254 struct sc_rpc_msg_s msg;
255 int ret;
256
257 if (!dev)
258 hang();
259
260 RPC_VER(&msg) = SC_RPC_VERSION;
261 RPC_SVC(&msg) = SC_RPC_SVC_MISC;
262 RPC_FUNC(&msg) = MISC_FUNC_BUILD_INFO;
263 RPC_SIZE(&msg) = 1;
264
265 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
266 if (ret < 0) {
267 printf("%s: err: %d\n", __func__, ret);
268 return;
269 }
270
271 if (build)
272 *build = RPC_U32(&msg, 0);
273 if (commit)
274 *commit = RPC_U32(&msg, 4);
275}
276
277int sc_misc_otp_fuse_read(sc_ipc_t ipc, u32 word, u32 *val)
278{
279 struct udevice *dev = gd->arch.scu_dev;
280 int size = sizeof(struct sc_rpc_msg_s);
281 struct sc_rpc_msg_s msg;
282 int ret;
283
284 if (!dev)
285 hang();
286
287 RPC_VER(&msg) = SC_RPC_VERSION;
288 RPC_SVC(&msg) = SC_RPC_SVC_MISC;
289 RPC_FUNC(&msg) = MISC_FUNC_OTP_FUSE_READ;
290 RPC_U32(&msg, 0) = word;
291 RPC_SIZE(&msg) = 2;
292
293 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
294 if (ret < 0)
295 return ret;
296
297 if (val)
298 *val = RPC_U32(&msg, 0U);
299
300 return 0;
301}
302
Peng Fanba44e012019-05-05 13:23:51 +0000303int sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource, sc_misc_temp_t temp,
304 s16 *celsius, s8 *tenths)
305{
306 struct udevice *dev = gd->arch.scu_dev;
307 int size = sizeof(struct sc_rpc_msg_s);
308 struct sc_rpc_msg_s msg;
309 int ret;
310
311 RPC_VER(&msg) = SC_RPC_VERSION;
312 RPC_SVC(&msg) = (u8)SC_RPC_SVC_MISC;
313 RPC_FUNC(&msg) = (u8)MISC_FUNC_GET_TEMP;
314 RPC_U16(&msg, 0U) = (u16)resource;
315 RPC_U8(&msg, 2U) = (u8)temp;
316 RPC_SIZE(&msg) = 2U;
317
318 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
319 if (ret < 0)
320 return ret;
321
322 if (celsius)
323 *celsius = RPC_I16(&msg, 0U);
324
325 if (tenths)
326 *tenths = RPC_I8(&msg, 2U);
327
328 return 0;
329}
330
Peng Fan55486382018-10-18 14:28:12 +0200331/* RM */
332sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr)
333{
334 struct udevice *dev = gd->arch.scu_dev;
335 int size = sizeof(struct sc_rpc_msg_s);
336 struct sc_rpc_msg_s msg;
337 int ret;
338 sc_err_t result;
339
340 if (!dev)
341 hang();
342
343 RPC_VER(&msg) = SC_RPC_VERSION;
344 RPC_SVC(&msg) = (u8)SC_RPC_SVC_RM;
345 RPC_FUNC(&msg) = (u8)RM_FUNC_IS_MEMREG_OWNED;
346 RPC_U8(&msg, 0U) = (u8)mr;
347 RPC_SIZE(&msg) = 2U;
348
349 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
350 result = RPC_R8(&msg);
351
352 if (result != 0 && result != 1) {
353 printf("%s: mr:%d res:%d\n", __func__, mr, RPC_R8(&msg));
354 if (ret)
355 printf("%s: mr:%d res:%d\n", __func__, mr,
356 RPC_R8(&msg));
357 }
358
359 return (sc_bool_t)result;
360}
361
Peng Fanb612a302019-08-26 08:12:03 +0000362int sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, sc_rm_sid_t sid)
363{
364 struct udevice *dev = gd->arch.scu_dev;
365 struct sc_rpc_msg_s msg;
366 int size = sizeof(struct sc_rpc_msg_s);
367 int ret;
368
369 RPC_VER(&msg) = SC_RPC_VERSION;
370 RPC_SVC(&msg) = (u8)SC_RPC_SVC_RM;
371 RPC_FUNC(&msg) = (u8)RM_FUNC_SET_MASTER_SID;
372 RPC_U16(&msg, 0U) = (u16)resource;
373 RPC_U16(&msg, 2U) = (u16)sid;
374 RPC_SIZE(&msg) = 2U;
375
376 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
377 if (ret)
378 printf("%s: resource:%d sid:%d: res:%d\n",
379 __func__, resource, sid, RPC_R8(&msg));
380
381 return ret;
382}
383
Peng Fan55486382018-10-18 14:28:12 +0200384int sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr, sc_faddr_t *addr_start,
385 sc_faddr_t *addr_end)
386{
387 struct udevice *dev = gd->arch.scu_dev;
388 int size = sizeof(struct sc_rpc_msg_s);
389 struct sc_rpc_msg_s msg;
390 int ret;
391
392 if (!dev)
393 hang();
394
395 RPC_VER(&msg) = SC_RPC_VERSION;
396 RPC_SVC(&msg) = (u8)SC_RPC_SVC_RM;
397 RPC_FUNC(&msg) = (u8)RM_FUNC_GET_MEMREG_INFO;
398 RPC_U8(&msg, 0U) = (u8)mr;
399 RPC_SIZE(&msg) = 2U;
400
401 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
402 if (ret)
403 printf("%s: mr:%d res:%d\n", __func__, mr, RPC_R8(&msg));
404
405 if (addr_start)
406 *addr_start = ((u64)RPC_U32(&msg, 0U) << 32U) |
407 RPC_U32(&msg, 4U);
408
409 if (addr_end)
410 *addr_end = ((u64)RPC_U32(&msg, 8U) << 32U) |
411 RPC_U32(&msg, 12U);
412
413 return ret;
414}
415
416sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource)
417{
418 struct udevice *dev = gd->arch.scu_dev;
419 int size = sizeof(struct sc_rpc_msg_s);
420 struct sc_rpc_msg_s msg;
421 int ret;
422 u8 result;
423
424 if (!dev)
425 hang();
426
427 RPC_VER(&msg) = SC_RPC_VERSION;
428 RPC_SVC(&msg) = (u8)SC_RPC_SVC_RM;
429 RPC_FUNC(&msg) = (u8)RM_FUNC_IS_RESOURCE_OWNED;
430 RPC_U16(&msg, 0U) = (u16)resource;
431 RPC_SIZE(&msg) = 2U;
432
433 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
434 result = RPC_R8(&msg);
435 if (result != 0 && result != 1) {
436 printf("%s: resource:%d res:%d\n",
437 __func__, resource, RPC_R8(&msg));
438 if (ret)
439 printf("%s: res:%d res:%d\n", __func__, resource,
440 RPC_R8(&msg));
441 }
442
443 return !!result;
444}