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
;
250 int cfe_getstdhandle(int flg
)
252 struct cfe_xiocb xiocb
;
254 xiocb
.xiocb_fcode
= CFE_CMD_DEV_GETHANDLE
;
255 xiocb
.xiocb_status
= 0;
256 xiocb
.xiocb_handle
= 0;
257 xiocb
.xiocb_flags
= flg
;
258 xiocb
.xiocb_psize
= 0;
260 cfe_iocb_dispatch(&xiocb
);
262 if (xiocb
.xiocb_status
< 0)
263 return xiocb
.xiocb_status
;
264 return xiocb
.xiocb_handle
;
270 struct cfe_xiocb xiocb
;
272 xiocb
.xiocb_fcode
= CFE_CMD_FW_GETTIME
;
273 xiocb
.xiocb_status
= 0;
274 xiocb
.xiocb_handle
= 0;
275 xiocb
.xiocb_flags
= 0;
276 xiocb
.xiocb_psize
= sizeof(struct xiocb_time
);
277 xiocb
.plist
.xiocb_time
.ticks
= 0;
279 cfe_iocb_dispatch(&xiocb
);
281 return xiocb
.plist
.xiocb_time
.ticks
;
285 int cfe_inpstat(int handle
)
287 struct cfe_xiocb xiocb
;
289 xiocb
.xiocb_fcode
= CFE_CMD_DEV_INPSTAT
;
290 xiocb
.xiocb_status
= 0;
291 xiocb
.xiocb_handle
= handle
;
292 xiocb
.xiocb_flags
= 0;
293 xiocb
.xiocb_psize
= sizeof(struct xiocb_inpstat
);
294 xiocb
.plist
.xiocb_inpstat
.inp_status
= 0;
296 cfe_iocb_dispatch(&xiocb
);
298 if (xiocb
.xiocb_status
< 0)
299 return xiocb
.xiocb_status
;
300 return xiocb
.plist
.xiocb_inpstat
.inp_status
;
304 cfe_ioctl(int handle
, unsigned int ioctlnum
, unsigned char *buffer
,
305 int length
, int *retlen
, u64 offset
)
307 struct cfe_xiocb xiocb
;
309 xiocb
.xiocb_fcode
= CFE_CMD_DEV_IOCTL
;
310 xiocb
.xiocb_status
= 0;
311 xiocb
.xiocb_handle
= handle
;
312 xiocb
.xiocb_flags
= 0;
313 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
314 xiocb
.plist
.xiocb_buffer
.buf_offset
= offset
;
315 xiocb
.plist
.xiocb_buffer
.buf_ioctlcmd
= ioctlnum
;
316 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(buffer
);
317 xiocb
.plist
.xiocb_buffer
.buf_length
= length
;
319 cfe_iocb_dispatch(&xiocb
);
322 *retlen
= xiocb
.plist
.xiocb_buffer
.buf_retlen
;
323 return xiocb
.xiocb_status
;
326 int cfe_open(char *name
)
328 struct cfe_xiocb xiocb
;
330 xiocb
.xiocb_fcode
= CFE_CMD_DEV_OPEN
;
331 xiocb
.xiocb_status
= 0;
332 xiocb
.xiocb_handle
= 0;
333 xiocb
.xiocb_flags
= 0;
334 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
335 xiocb
.plist
.xiocb_buffer
.buf_offset
= 0;
336 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(name
);
337 xiocb
.plist
.xiocb_buffer
.buf_length
= strlen(name
);
339 cfe_iocb_dispatch(&xiocb
);
341 if (xiocb
.xiocb_status
< 0)
342 return xiocb
.xiocb_status
;
343 return xiocb
.xiocb_handle
;
346 int cfe_read(int handle
, unsigned char *buffer
, int length
)
348 return cfe_readblk(handle
, 0, buffer
, length
);
351 int cfe_readblk(int handle
, s64 offset
, unsigned char *buffer
, int length
)
353 struct cfe_xiocb xiocb
;
355 xiocb
.xiocb_fcode
= CFE_CMD_DEV_READ
;
356 xiocb
.xiocb_status
= 0;
357 xiocb
.xiocb_handle
= handle
;
358 xiocb
.xiocb_flags
= 0;
359 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
360 xiocb
.plist
.xiocb_buffer
.buf_offset
= offset
;
361 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(buffer
);
362 xiocb
.plist
.xiocb_buffer
.buf_length
= length
;
364 cfe_iocb_dispatch(&xiocb
);
366 if (xiocb
.xiocb_status
< 0)
367 return xiocb
.xiocb_status
;
368 return xiocb
.plist
.xiocb_buffer
.buf_retlen
;
371 int cfe_setenv(char *name
, char *val
)
373 struct cfe_xiocb xiocb
;
375 xiocb
.xiocb_fcode
= CFE_CMD_ENV_SET
;
376 xiocb
.xiocb_status
= 0;
377 xiocb
.xiocb_handle
= 0;
378 xiocb
.xiocb_flags
= 0;
379 xiocb
.xiocb_psize
= sizeof(struct xiocb_envbuf
);
380 xiocb
.plist
.xiocb_envbuf
.enum_idx
= 0;
381 xiocb
.plist
.xiocb_envbuf
.name_ptr
= XPTR_FROM_NATIVE(name
);
382 xiocb
.plist
.xiocb_envbuf
.name_length
= strlen(name
);
383 xiocb
.plist
.xiocb_envbuf
.val_ptr
= XPTR_FROM_NATIVE(val
);
384 xiocb
.plist
.xiocb_envbuf
.val_length
= strlen(val
);
386 cfe_iocb_dispatch(&xiocb
);
388 return xiocb
.xiocb_status
;
391 int cfe_write(int handle
, const char *buffer
, int length
)
393 return cfe_writeblk(handle
, 0, buffer
, length
);
396 int cfe_writeblk(int handle
, s64 offset
, const char *buffer
, int length
)
398 struct cfe_xiocb xiocb
;
400 xiocb
.xiocb_fcode
= CFE_CMD_DEV_WRITE
;
401 xiocb
.xiocb_status
= 0;
402 xiocb
.xiocb_handle
= handle
;
403 xiocb
.xiocb_flags
= 0;
404 xiocb
.xiocb_psize
= sizeof(struct xiocb_buffer
);
405 xiocb
.plist
.xiocb_buffer
.buf_offset
= offset
;
406 xiocb
.plist
.xiocb_buffer
.buf_ptr
= XPTR_FROM_NATIVE(buffer
);
407 xiocb
.plist
.xiocb_buffer
.buf_length
= length
;
409 cfe_iocb_dispatch(&xiocb
);
411 if (xiocb
.xiocb_status
< 0)
412 return xiocb
.xiocb_status
;
413 return xiocb
.plist
.xiocb_buffer
.buf_retlen
;