1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
8 * Broadcom Common Firmware Environment (CFE)
10 * This module contains device function stubs (small routines to
11 * call the standard "iocb" interface entry point to CFE).
12 * There should be one routine here per iocb function call.
14 * Authors: Mitch Lichtenberg, Chris Demetriou
17 #include <asm/fw/cfe/cfe_api.h>
18 #include "cfe_api_int.h"
20 /* Cast from a native pointer to a cfe_xptr_t and back. */
21 #define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
22 #define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
24 int cfe_iocb_dispatch(struct cfe_xiocb
*xiocb
);
27 * Declare the dispatch function with args of "intptr_t".
28 * This makes sure whatever model we're compiling in
29 * puts the pointers in a single register. For example,
30 * combining -mlong64 and -mips1 or -mips2 would lead to
31 * trouble, since the handle and IOCB pointer will be
32 * passed in two registers each, and CFE expects one.
35 static int (*cfe_dispfunc
) (intptr_t handle
, intptr_t xiocb
);
36 static u64 cfe_handle
;
38 int cfe_init(u64 handle
, u64 ept
)
40 cfe_dispfunc
= NATIVE_FROM_XPTR(ept
);
45 int cfe_iocb_dispatch(struct cfe_xiocb
* xiocb
)
49 return (*cfe_dispfunc
) ((intptr_t) cfe_handle
, (intptr_t) xiocb
);
52 int cfe_close(int handle
)
54 struct cfe_xiocb xiocb
;
56 xiocb
.xiocb_fcode
= CFE_CMD_DEV_CLOSE
;
57 xiocb
.xiocb_status
= 0;
58 xiocb
.xiocb_handle
= handle
;
59 xiocb
.xiocb_flags
= 0;
60 xiocb
.xiocb_psize
= 0;
62 cfe_iocb_dispatch(&xiocb
);
64 return xiocb
.xiocb_status
;
68 int cfe_cpu_start(int cpu
, void (*fn
) (void), long sp
, long gp
, long a1
)
70 struct cfe_xiocb xiocb
;
72 xiocb
.xiocb_fcode
= CFE_CMD_FW_CPUCTL
;
73 xiocb
.xiocb_status
= 0;
74 xiocb
.xiocb_handle
= 0;
75 xiocb
.xiocb_flags
= 0;
76 xiocb
.xiocb_psize
= sizeof(struct xiocb_cpuctl
);
77 xiocb
.plist
.xiocb_cpuctl
.cpu_number
= cpu
;
78 xiocb
.plist
.xiocb_cpuctl
.cpu_command
= CFE_CPU_CMD_START
;
79 xiocb
.plist
.xiocb_cpuctl
.gp_val
= gp
;
80 xiocb
.plist
.xiocb_cpuctl
.sp_val
= sp
;
81 xiocb
.plist
.xiocb_cpuctl
.a1_val
= a1
;
82 xiocb
.plist
.xiocb_cpuctl
.start_addr
= (long) fn
;
84 cfe_iocb_dispatch(&xiocb
);
86 return xiocb
.xiocb_status
;
89 int cfe_cpu_stop(int cpu
)
91 struct cfe_xiocb xiocb
;
93 xiocb
.xiocb_fcode
= CFE_CMD_FW_CPUCTL
;
94 xiocb
.xiocb_status
= 0;
95 xiocb
.xiocb_handle
= 0;
96 xiocb
.xiocb_flags
= 0;
97 xiocb
.xiocb_psize
= sizeof(struct xiocb_cpuctl
);
98 xiocb
.plist
.xiocb_cpuctl
.cpu_number
= cpu
;
99 xiocb
.plist
.xiocb_cpuctl
.cpu_command
= CFE_CPU_CMD_STOP
;
101 cfe_iocb_dispatch(&xiocb
);
103 return xiocb
.xiocb_status
;
106 int cfe_enumenv(int idx
, char *name
, int namelen
, char *val
, int vallen
)
108 struct cfe_xiocb xiocb
;
110 xiocb
.xiocb_fcode
= CFE_CMD_ENV_SET
;
111 xiocb
.xiocb_status
= 0;
112 xiocb
.xiocb_handle
= 0;
113 xiocb
.xiocb_flags
= 0;
114 xiocb
.xiocb_psize
= sizeof(struct xiocb_envbuf
);
115 xiocb
.plist
.xiocb_envbuf
.enum_idx
= idx
;
116 xiocb
.plist
.xiocb_envbuf
.name_ptr
= XPTR_FROM_NATIVE(name
);
117 xiocb
.plist
.xiocb_envbuf
.name_length
= namelen
;
118 xiocb
.plist
.xiocb_envbuf
.val_ptr
= XPTR_FROM_NATIVE(val
);
119 xiocb
.plist
.xiocb_envbuf
.val_length
= vallen
;
121 cfe_iocb_dispatch(&xiocb
);
123 return xiocb
.xiocb_status
;
127 cfe_enummem(int idx
, int flags
, u64
*start
, u64
*length
, u64
*type
)
129 struct cfe_xiocb xiocb
;
131 xiocb
.xiocb_fcode
= CFE_CMD_FW_MEMENUM
;
132 xiocb
.xiocb_status
= 0;
133 xiocb
.xiocb_handle
= 0;
134 xiocb
.xiocb_flags
= flags
;
135 xiocb
.xiocb_psize
= sizeof(struct xiocb_meminfo
);
136 xiocb
.plist
.xiocb_meminfo
.mi_idx
= idx
;
138 cfe_iocb_dispatch(&xiocb
);
140 if (xiocb
.xiocb_status
< 0)
141 return xiocb
.xiocb_status
;
143 *start
= xiocb
.plist
.xiocb_meminfo
.mi_addr
;
144 *length
= xiocb
.plist
.xiocb_meminfo
.mi_size
;
145 *type
= xiocb
.plist
.xiocb_meminfo
.mi_type
;
150 int cfe_exit(int warm
, int status
)
152 struct cfe_xiocb xiocb
;
154 xiocb
.xiocb_fcode
= CFE_CMD_FW_RESTART
;
155 xiocb
.xiocb_status
= 0;
156 xiocb
.xiocb_handle
= 0;
157 xiocb
.xiocb_flags
= warm
? CFE_FLG_WARMSTART
: 0;
158 xiocb
.xiocb_psize
= sizeof(struct xiocb_exitstat
);
159 xiocb
.plist
.xiocb_exitstat
.status
= status
;
161 cfe_iocb_dispatch(&xiocb
);
163 return xiocb
.xiocb_status
;
166 int cfe_flushcache(int flg
)
168 struct cfe_xiocb xiocb
;
170 xiocb
.xiocb_fcode
= CFE_CMD_FW_FLUSHCACHE
;
171 xiocb
.xiocb_status
= 0;
172 xiocb
.xiocb_handle
= 0;
173 xiocb
.xiocb_flags
= flg
;
174 xiocb
.xiocb_psize
= 0;
176 cfe_iocb_dispatch(&xiocb
);
178 return xiocb
.xiocb_status
;
181 int cfe_getdevinfo(char *name
)
183 struct cfe_xiocb xiocb
;
185 xiocb
.xiocb_fcode
= CFE_CMD_DEV_GETINFO
;
186 xiocb
.xiocb_status
= 0;
187 xiocb
.xiocb_handle
= 0;
188 xiocb
.xiocb_flags
= 0;
189 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
190 xiocb
.plist
.xiocb_buffer
.buf_offset
= 0;
191 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(name
);
192 xiocb
.plist
.xiocb_buffer
.buf_length
= strlen(name
);
194 cfe_iocb_dispatch(&xiocb
);
196 if (xiocb
.xiocb_status
< 0)
197 return xiocb
.xiocb_status
;
198 return xiocb
.plist
.xiocb_buffer
.buf_ioctlcmd
;
201 int cfe_getenv(char *name
, char *dest
, int destlen
)
203 struct cfe_xiocb xiocb
;
207 xiocb
.xiocb_fcode
= CFE_CMD_ENV_GET
;
208 xiocb
.xiocb_status
= 0;
209 xiocb
.xiocb_handle
= 0;
210 xiocb
.xiocb_flags
= 0;
211 xiocb
.xiocb_psize
= sizeof(struct xiocb_envbuf
);
212 xiocb
.plist
.xiocb_envbuf
.enum_idx
= 0;
213 xiocb
.plist
.xiocb_envbuf
.name_ptr
= XPTR_FROM_NATIVE(name
);
214 xiocb
.plist
.xiocb_envbuf
.name_length
= strlen(name
);
215 xiocb
.plist
.xiocb_envbuf
.val_ptr
= XPTR_FROM_NATIVE(dest
);
216 xiocb
.plist
.xiocb_envbuf
.val_length
= destlen
;
218 cfe_iocb_dispatch(&xiocb
);
220 return xiocb
.xiocb_status
;
223 int cfe_getfwinfo(cfe_fwinfo_t
* info
)
225 struct cfe_xiocb xiocb
;
227 xiocb
.xiocb_fcode
= CFE_CMD_FW_GETINFO
;
228 xiocb
.xiocb_status
= 0;
229 xiocb
.xiocb_handle
= 0;
230 xiocb
.xiocb_flags
= 0;
231 xiocb
.xiocb_psize
= sizeof(struct xiocb_fwinfo
);
233 cfe_iocb_dispatch(&xiocb
);
235 if (xiocb
.xiocb_status
< 0)
236 return xiocb
.xiocb_status
;
238 info
->fwi_version
= xiocb
.plist
.xiocb_fwinfo
.fwi_version
;
239 info
->fwi_totalmem
= xiocb
.plist
.xiocb_fwinfo
.fwi_totalmem
;
240 info
->fwi_flags
= xiocb
.plist
.xiocb_fwinfo
.fwi_flags
;
241 info
->fwi_boardid
= xiocb
.plist
.xiocb_fwinfo
.fwi_boardid
;
242 info
->fwi_bootarea_va
= xiocb
.plist
.xiocb_fwinfo
.fwi_bootarea_va
;
243 info
->fwi_bootarea_pa
= xiocb
.plist
.xiocb_fwinfo
.fwi_bootarea_pa
;
244 info
->fwi_bootarea_size
=
245 xiocb
.plist
.xiocb_fwinfo
.fwi_bootarea_size
;
247 info
->fwi_reserved1
= xiocb
.plist
.xiocb_fwinfo
.fwi_reserved1
;
248 info
->fwi_reserved2
= xiocb
.plist
.xiocb_fwinfo
.fwi_reserved2
;
249 info
->fwi_reserved3
= xiocb
.plist
.xiocb_fwinfo
.fwi_reserved3
;
255 int cfe_getstdhandle(int flg
)
257 struct cfe_xiocb xiocb
;
259 xiocb
.xiocb_fcode
= CFE_CMD_DEV_GETHANDLE
;
260 xiocb
.xiocb_status
= 0;
261 xiocb
.xiocb_handle
= 0;
262 xiocb
.xiocb_flags
= flg
;
263 xiocb
.xiocb_psize
= 0;
265 cfe_iocb_dispatch(&xiocb
);
267 if (xiocb
.xiocb_status
< 0)
268 return xiocb
.xiocb_status
;
269 return xiocb
.xiocb_handle
;
275 struct cfe_xiocb xiocb
;
277 xiocb
.xiocb_fcode
= CFE_CMD_FW_GETTIME
;
278 xiocb
.xiocb_status
= 0;
279 xiocb
.xiocb_handle
= 0;
280 xiocb
.xiocb_flags
= 0;
281 xiocb
.xiocb_psize
= sizeof(struct xiocb_time
);
282 xiocb
.plist
.xiocb_time
.ticks
= 0;
284 cfe_iocb_dispatch(&xiocb
);
286 return xiocb
.plist
.xiocb_time
.ticks
;
290 int cfe_inpstat(int handle
)
292 struct cfe_xiocb xiocb
;
294 xiocb
.xiocb_fcode
= CFE_CMD_DEV_INPSTAT
;
295 xiocb
.xiocb_status
= 0;
296 xiocb
.xiocb_handle
= handle
;
297 xiocb
.xiocb_flags
= 0;
298 xiocb
.xiocb_psize
= sizeof(struct xiocb_inpstat
);
299 xiocb
.plist
.xiocb_inpstat
.inp_status
= 0;
301 cfe_iocb_dispatch(&xiocb
);
303 if (xiocb
.xiocb_status
< 0)
304 return xiocb
.xiocb_status
;
305 return xiocb
.plist
.xiocb_inpstat
.inp_status
;
309 cfe_ioctl(int handle
, unsigned int ioctlnum
, unsigned char *buffer
,
310 int length
, int *retlen
, u64 offset
)
312 struct cfe_xiocb xiocb
;
314 xiocb
.xiocb_fcode
= CFE_CMD_DEV_IOCTL
;
315 xiocb
.xiocb_status
= 0;
316 xiocb
.xiocb_handle
= handle
;
317 xiocb
.xiocb_flags
= 0;
318 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
319 xiocb
.plist
.xiocb_buffer
.buf_offset
= offset
;
320 xiocb
.plist
.xiocb_buffer
.buf_ioctlcmd
= ioctlnum
;
321 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(buffer
);
322 xiocb
.plist
.xiocb_buffer
.buf_length
= length
;
324 cfe_iocb_dispatch(&xiocb
);
327 *retlen
= xiocb
.plist
.xiocb_buffer
.buf_retlen
;
328 return xiocb
.xiocb_status
;
331 int cfe_open(char *name
)
333 struct cfe_xiocb xiocb
;
335 xiocb
.xiocb_fcode
= CFE_CMD_DEV_OPEN
;
336 xiocb
.xiocb_status
= 0;
337 xiocb
.xiocb_handle
= 0;
338 xiocb
.xiocb_flags
= 0;
339 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
340 xiocb
.plist
.xiocb_buffer
.buf_offset
= 0;
341 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(name
);
342 xiocb
.plist
.xiocb_buffer
.buf_length
= strlen(name
);
344 cfe_iocb_dispatch(&xiocb
);
346 if (xiocb
.xiocb_status
< 0)
347 return xiocb
.xiocb_status
;
348 return xiocb
.xiocb_handle
;
351 int cfe_read(int handle
, unsigned char *buffer
, int length
)
353 return cfe_readblk(handle
, 0, buffer
, length
);
356 int cfe_readblk(int handle
, s64 offset
, unsigned char *buffer
, int length
)
358 struct cfe_xiocb xiocb
;
360 xiocb
.xiocb_fcode
= CFE_CMD_DEV_READ
;
361 xiocb
.xiocb_status
= 0;
362 xiocb
.xiocb_handle
= handle
;
363 xiocb
.xiocb_flags
= 0;
364 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
365 xiocb
.plist
.xiocb_buffer
.buf_offset
= offset
;
366 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(buffer
);
367 xiocb
.plist
.xiocb_buffer
.buf_length
= length
;
369 cfe_iocb_dispatch(&xiocb
);
371 if (xiocb
.xiocb_status
< 0)
372 return xiocb
.xiocb_status
;
373 return xiocb
.plist
.xiocb_buffer
.buf_retlen
;
376 int cfe_setenv(char *name
, char *val
)
378 struct cfe_xiocb xiocb
;
380 xiocb
.xiocb_fcode
= CFE_CMD_ENV_SET
;
381 xiocb
.xiocb_status
= 0;
382 xiocb
.xiocb_handle
= 0;
383 xiocb
.xiocb_flags
= 0;
384 xiocb
.xiocb_psize
= sizeof(struct xiocb_envbuf
);
385 xiocb
.plist
.xiocb_envbuf
.enum_idx
= 0;
386 xiocb
.plist
.xiocb_envbuf
.name_ptr
= XPTR_FROM_NATIVE(name
);
387 xiocb
.plist
.xiocb_envbuf
.name_length
= strlen(name
);
388 xiocb
.plist
.xiocb_envbuf
.val_ptr
= XPTR_FROM_NATIVE(val
);
389 xiocb
.plist
.xiocb_envbuf
.val_length
= strlen(val
);
391 cfe_iocb_dispatch(&xiocb
);
393 return xiocb
.xiocb_status
;
396 int cfe_write(int handle
, const char *buffer
, int length
)
398 return cfe_writeblk(handle
, 0, buffer
, length
);
401 int cfe_writeblk(int handle
, s64 offset
, const char *buffer
, int length
)
403 struct cfe_xiocb xiocb
;
405 xiocb
.xiocb_fcode
= CFE_CMD_DEV_WRITE
;
406 xiocb
.xiocb_status
= 0;
407 xiocb
.xiocb_handle
= handle
;
408 xiocb
.xiocb_flags
= 0;
409 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
410 xiocb
.plist
.xiocb_buffer
.buf_offset
= offset
;
411 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(buffer
);
412 xiocb
.plist
.xiocb_buffer
.buf_length
= length
;
414 cfe_iocb_dispatch(&xiocb
);
416 if (xiocb
.xiocb_status
< 0)
417 return xiocb
.xiocb_status
;
418 return xiocb
.plist
.xiocb_buffer
.buf_retlen
;