2 * Broadcom Common Firmware Environment (CFE) support
4 * Copyright 2000, 2001, 2002
5 * Broadcom Corporation. All rights reserved.
7 * Copyright (C) 2006 Michael Buesch
9 * Original Authors: Mitch Lichtenberg, Chris Demetriou
11 * This software is furnished under license and may be used and copied only
12 * in accordance with the following terms and conditions. Subject to these
13 * conditions, you may download, copy, install, use, modify and distribute
14 * modified or unmodified copies of this software in source and/or binary
15 * form. No title or ownership is transferred hereby.
17 * 1) Any source code used, modified or distributed must reproduce and
18 * retain this copyright notice and list of conditions as they appear in
21 * 2) No right is granted to use any trade name, trademark, or logo of
22 * Broadcom Corporation. The "Broadcom Corporation" name may not be
23 * used to endorse or promote products derived from this software
24 * without the prior written permission of Broadcom Corporation.
26 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
29 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
30 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
31 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
34 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
36 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <linux/init.h>
40 #include <linux/string.h>
41 #include <linux/errno.h>
42 #include <linux/spinlock.h>
45 #include "cfe_private.h"
48 static cfe_uint_t cfe_handle
;
49 static int (*cfe_trampoline
)(long handle
, long iocb
);
52 #include <linux/kernel.h>
54 void __init
cfe_setup(unsigned long fwarg0
, unsigned long fwarg1
,
55 unsigned long fwarg2
, unsigned long fwarg3
)
57 if (fwarg3
== 0x80300000) {
58 /* WRT54G workaround */
62 if (fwarg3
!= CFE_EPTSEAL
) {
63 /* We are not booted from CFE */
67 /* We are on the boot CPU */
68 cfe_handle
= (cfe_uint_t
)fwarg0
;
69 cfe_trampoline
= CFE_TO_PTR(fwarg2
);
73 int cfe_vprintk(const char *fmt
, va_list args
)
75 static char buffer
[1024];
76 static DEFINE_SPINLOCK(lock
);
77 static const char pfx
[] = "CFE-console: ";
78 static const size_t pfx_len
= sizeof(pfx
) - 1;
87 spin_lock_irqsave(&lock
, flags
);
88 handle
= cfe_getstdhandle(CFE_STDHANDLE_CONSOLE
);
89 if (CFE_ISERR(handle
)) {
94 len
= vscnprintf(buffer
+ pfx_len
,
95 sizeof(buffer
) - pfx_len
- 2,
98 /* The CFE console requires CR-LF line-ends.
99 * Add a CR, if we only terminate lines with a LF.
100 * This does only fix CR-LF at the end of the string.
101 * So for multiple lines, use multiple cfe_vprintk calls.
104 buffer
[len
- 1] == '\n' && buffer
[len
- 2] != '\r') {
105 buffer
[len
- 1] = '\r';
112 res
= cfe_write(handle
, buffer
+ pos
, len
- pos
);
113 if (CFE_ISERR(res
)) {
121 spin_unlock_irqrestore(&lock
, flags
);
126 int cfe_printk(const char *fmt
, ...)
132 res
= cfe_vprintk(fmt
, args
);
138 static int cfe_iocb_dispatch(struct cfe_iocb
*iocb
)
141 return CFE_ERR_UNSUPPORTED
;
142 return cfe_trampoline((long)cfe_handle
, (long)iocb
);
145 int cfe_present(void)
147 return (cfe_trampoline
!= NULL
);
150 int cfe_close(int handle
)
152 struct cfe_iocb iocb
;
155 memset(&iocb
, 0, sizeof(iocb
));
156 iocb
.fcode
= CFE_CMD_DEV_CLOSE
;
157 iocb
.handle
= handle
;
159 err
= cfe_iocb_dispatch(&iocb
);
161 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
164 int cfe_cpu_start(int cpu
, void (*fn
)(void), long sp
, long gp
, long a1
)
166 struct cfe_iocb iocb
;
169 memset(&iocb
, 0, sizeof(iocb
));
170 iocb
.fcode
= CFE_CMD_FW_CPUCTL
;
171 iocb
.psize
= sizeof(struct cfe_iocb_cpuctl
);
172 iocb
.cpuctl
.number
= cpu
;
173 iocb
.cpuctl
.command
= CFE_CPU_CMD_START
;
177 iocb
.cpuctl
.start_addr
= (long)fn
;
179 err
= cfe_iocb_dispatch(&iocb
);
181 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
184 int cfe_cpu_stop(int cpu
)
186 struct cfe_iocb iocb
;
189 memset(&iocb
, 0, sizeof(iocb
));
190 iocb
.fcode
= CFE_CMD_FW_CPUCTL
;
191 iocb
.psize
= sizeof(struct cfe_iocb_cpuctl
);
192 iocb
.cpuctl
.number
= cpu
;
193 iocb
.cpuctl
.command
= CFE_CPU_CMD_STOP
;
195 err
= cfe_iocb_dispatch(&iocb
);
197 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
200 int cfe_enumenv(int idx
, char *name
, int namelen
, char *val
, int vallen
)
202 struct cfe_iocb iocb
;
205 memset(&iocb
, 0, sizeof(iocb
));
206 iocb
.fcode
= CFE_CMD_ENV_ENUM
;
207 iocb
.psize
= sizeof(struct cfe_iocb_envbuf
);
208 iocb
.envbuf
.index
= idx
;
209 iocb
.envbuf
.name
= PTR_TO_CFE(name
);
210 iocb
.envbuf
.name_len
= namelen
;
211 iocb
.envbuf
.val
= PTR_TO_CFE(val
);
212 iocb
.envbuf
.val_len
= vallen
;
214 err
= cfe_iocb_dispatch(&iocb
);
216 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
219 int cfe_enumdev(int idx
, char *name
, int namelen
)
221 struct cfe_iocb iocb
;
224 memset(&iocb
, 0, sizeof(iocb
));
226 iocb
.fcode
= CFE_CMD_DEV_ENUM
;
227 iocb
.psize
= sizeof(struct cfe_iocb_envbuf
);
228 iocb
.envbuf
.index
= idx
;
229 iocb
.envbuf
.name
= PTR_TO_CFE(name
);
230 iocb
.envbuf
.name_len
= namelen
;
232 err
= cfe_iocb_dispatch(&iocb
);
234 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
237 int cfe_enummem(int idx
, int flags
, u64
*start
, u64
*length
,
240 struct cfe_iocb iocb
;
243 memset(&iocb
, 0, sizeof(iocb
));
245 iocb
.fcode
= CFE_CMD_FW_MEMENUM
;
247 iocb
.psize
= sizeof(struct cfe_iocb_meminfo
);
248 iocb
.meminfo
.index
= idx
;
250 err
= cfe_iocb_dispatch(&iocb
);
253 if (!CFE_ISERR(iocb
.status
)) {
254 *start
= iocb
.meminfo
.addr
;
255 *length
= iocb
.meminfo
.size
;
256 *type
= iocb
.meminfo
.type
;
262 int cfe_exit(int warm
, int status
)
264 struct cfe_iocb iocb
;
267 printk("CFE REBOOT\n");
268 memset(&iocb
, 0, sizeof(iocb
));
269 iocb
.fcode
= CFE_CMD_FW_RESTART
;
271 iocb
.flags
= CFE_FLG_WARMSTART
;
272 iocb
.psize
= sizeof(struct cfe_iocb_exitstat
);
273 iocb
.exitstat
.status
= status
;
276 err
= cfe_iocb_dispatch(&iocb
);
279 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
282 int cfe_flushcache(int flags
)
284 struct cfe_iocb iocb
;
287 memset(&iocb
, 0, sizeof(iocb
));
288 iocb
.fcode
= CFE_CMD_FW_FLUSHCACHE
;
291 err
= cfe_iocb_dispatch(&iocb
);
293 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
296 int cfe_getdevinfo(char *name
)
298 struct cfe_iocb iocb
;
301 memset(&iocb
, 0, sizeof(iocb
));
302 iocb
.fcode
= CFE_CMD_DEV_GETINFO
;
303 iocb
.psize
= sizeof(struct cfe_iocb_buf
);
304 iocb
.buffer
.ptr
= PTR_TO_CFE(name
);
305 iocb
.buffer
.length
= strlen(name
);
307 err
= cfe_iocb_dispatch(&iocb
);
310 if (CFE_ISERR(iocb
.status
))
313 return iocb
.buffer
.devflags
;
316 int cfe_getenv(char *name
, char *dest
, int destlen
)
318 struct cfe_iocb iocb
;
322 memset(&iocb
, 0, sizeof(iocb
));
323 iocb
.fcode
= CFE_CMD_ENV_GET
;
324 iocb
.psize
= sizeof(struct cfe_iocb_envbuf
);
325 iocb
.envbuf
.name
= PTR_TO_CFE(name
);
326 iocb
.envbuf
.name_len
= strlen(name
);
327 iocb
.envbuf
.val
= PTR_TO_CFE(dest
);
328 iocb
.envbuf
.val_len
= destlen
;
330 err
= cfe_iocb_dispatch(&iocb
);
332 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
335 int cfe_getfwinfo(struct cfe_fwinfo
*info
)
337 struct cfe_iocb iocb
;
340 memset(&iocb
, 0, sizeof(iocb
));
341 iocb
.fcode
= CFE_CMD_FW_GETINFO
;
342 iocb
.psize
= sizeof(struct cfe_iocb_fwinfo
);
344 err
= cfe_iocb_dispatch(&iocb
);
347 if (CFE_ISERR(iocb
.status
))
350 info
->version
= iocb
.fwinfo
.version
;
351 info
->totalmem
= iocb
.fwinfo
.totalmem
;
352 info
->flags
= iocb
.fwinfo
.flags
;
353 info
->boardid
= iocb
.fwinfo
.boardid
;
354 info
->bootarea_va
= iocb
.fwinfo
.bootarea_va
;
355 info
->bootarea_pa
= iocb
.fwinfo
.bootarea_pa
;
356 info
->bootarea_size
= iocb
.fwinfo
.bootarea_size
;
361 int cfe_getstdhandle(int handletype
)
363 struct cfe_iocb iocb
;
366 memset(&iocb
, 0, sizeof(iocb
));
367 iocb
.fcode
= CFE_CMD_DEV_GETHANDLE
;
368 iocb
.flags
= handletype
;
370 err
= cfe_iocb_dispatch(&iocb
);
373 if (CFE_ISERR(iocb
.status
))
379 int cfe_getticks(s64
*ticks
)
381 struct cfe_iocb iocb
;
384 memset(&iocb
, 0, sizeof(iocb
));
385 iocb
.fcode
= CFE_CMD_FW_GETTIME
;
386 iocb
.psize
= sizeof(struct cfe_iocb_time
);
388 err
= cfe_iocb_dispatch(&iocb
);
391 if (!CFE_ISERR(iocb
.status
))
392 *ticks
= iocb
.time
.ticks
;
397 int cfe_inpstat(int handle
)
399 struct cfe_iocb iocb
;
402 memset(&iocb
, 0, sizeof(iocb
));
403 iocb
.fcode
= CFE_CMD_DEV_INPSTAT
;
404 iocb
.handle
= handle
;
405 iocb
.psize
= sizeof(struct cfe_iocb_inpstat
);
407 err
= cfe_iocb_dispatch(&iocb
);
410 if (CFE_ISERR(iocb
.status
))
413 return iocb
.inpstat
.status
;
416 int cfe_ioctl(int handle
, unsigned int ioctlnum
,
417 unsigned char *buffer
, int length
,
418 int *retlen
, u64 offset
)
420 struct cfe_iocb iocb
;
423 memset(&iocb
, 0, sizeof(iocb
));
424 iocb
.fcode
= CFE_CMD_DEV_IOCTL
;
425 iocb
.handle
= handle
;
426 iocb
.psize
= sizeof(struct cfe_iocb_buf
);
427 iocb
.buffer
.offset
= offset
;
428 iocb
.buffer
.ioctlcmd
= ioctlnum
;
429 iocb
.buffer
.ptr
= PTR_TO_CFE(buffer
);
430 iocb
.buffer
.length
= length
;
432 err
= cfe_iocb_dispatch(&iocb
);
435 if (CFE_ISERR(iocb
.status
))
438 *retlen
= iocb
.buffer
.retlen
;
443 int cfe_open(char *name
)
445 struct cfe_iocb iocb
;
448 memset(&iocb
, 0, sizeof(iocb
));
449 iocb
.fcode
= CFE_CMD_DEV_OPEN
;
450 iocb
.psize
= sizeof(struct cfe_iocb_buf
);
451 iocb
.buffer
.ptr
= PTR_TO_CFE(name
);
452 iocb
.buffer
.length
= strlen(name
);
454 err
= cfe_iocb_dispatch(&iocb
);
457 if (CFE_ISERR(iocb
.status
))
463 int cfe_read(int handle
, unsigned char *buffer
, int length
)
465 return cfe_readblk(handle
, 0, buffer
, length
);
468 int cfe_readblk(int handle
, s64 offset
, unsigned char *buffer
, int length
)
470 struct cfe_iocb iocb
;
473 memset(&iocb
, 0, sizeof(iocb
));
474 iocb
.fcode
= CFE_CMD_DEV_READ
;
475 iocb
.handle
= handle
;
476 iocb
.psize
= sizeof(struct cfe_iocb_buf
);
477 iocb
.buffer
.offset
= offset
;
478 iocb
.buffer
.ptr
= PTR_TO_CFE(buffer
);
479 iocb
.buffer
.length
= length
;
481 err
= cfe_iocb_dispatch(&iocb
);
484 if (CFE_ISERR(iocb
.status
))
487 return iocb
.buffer
.retlen
;
490 int cfe_setenv(char *name
, char *val
)
492 struct cfe_iocb iocb
;
495 memset(&iocb
, 0, sizeof(iocb
));
496 iocb
.fcode
= CFE_CMD_ENV_SET
;
497 iocb
.psize
= sizeof(struct cfe_iocb_envbuf
);
498 iocb
.envbuf
.name
= PTR_TO_CFE(name
);
499 iocb
.envbuf
.name_len
= strlen(name
);
500 iocb
.envbuf
.val
= PTR_TO_CFE(val
);
501 iocb
.envbuf
.val_len
= strlen(val
);
503 err
= cfe_iocb_dispatch(&iocb
);
505 return (CFE_ISERR(err
)) ? err
: iocb
.status
;
508 int cfe_write(int handle
, unsigned char *buffer
, int length
)
510 return cfe_writeblk(handle
, 0, buffer
, length
);
513 int cfe_writeblk(int handle
, s64 offset
, unsigned char *buffer
, int length
)
515 struct cfe_iocb iocb
;
518 memset(&iocb
, 0, sizeof(iocb
));
519 iocb
.fcode
= CFE_CMD_DEV_WRITE
;
520 iocb
.handle
= handle
;
521 iocb
.psize
= sizeof(struct cfe_iocb_buf
);
522 iocb
.buffer
.offset
= offset
;
523 iocb
.buffer
.ptr
= PTR_TO_CFE(buffer
);
524 iocb
.buffer
.length
= length
;
526 err
= cfe_iocb_dispatch(&iocb
);
529 if (CFE_ISERR(iocb
.status
))
532 return iocb
.buffer
.retlen
;
This page took 0.068394 seconds and 5 git commands to generate.