123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
- */
- /*
- *
- * Broadcom Common Firmware Environment (CFE)
- *
- * This module contains device function stubs (small routines to
- * call the standard "iocb" interface entry point to CFE).
- * There should be one routine here per iocb function call.
- *
- * Authors: Mitch Lichtenberg, Chris Demetriou
- */
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/printk.h>
- #include <asm/mipsregs.h>
- #include <asm/fw/cfe/cfe_api.h>
- #include "cfe_api_int.h"
- unsigned long __initdata cfe_seal;
- /* Cast from a native pointer to a cfe_xptr_t and back. */
- #define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
- #define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
- int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
- /*
- * Declare the dispatch function with args of "intptr_t".
- * This makes sure whatever model we're compiling in
- * puts the pointers in a single register. For example,
- * combining -mlong64 and -mips1 or -mips2 would lead to
- * trouble, since the handle and IOCB pointer will be
- * passed in two registers each, and CFE expects one.
- */
- static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
- static u64 cfe_handle;
- int cfe_init(u64 handle, u64 ept)
- {
- cfe_dispfunc = NATIVE_FROM_XPTR(ept);
- cfe_handle = handle;
- return 0;
- }
- int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
- {
- if (!cfe_dispfunc)
- return -1;
- return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
- }
- int cfe_close(int handle)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = 0;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
- xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
- xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
- xiocb.plist.xiocb_cpuctl.gp_val = gp;
- xiocb.plist.xiocb_cpuctl.sp_val = sp;
- xiocb.plist.xiocb_cpuctl.a1_val = a1;
- xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int cfe_cpu_stop(int cpu)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
- xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
- xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
- xiocb.plist.xiocb_envbuf.enum_idx = idx;
- xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_envbuf.name_length = namelen;
- xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
- xiocb.plist.xiocb_envbuf.val_length = vallen;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int
- cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = flags;
- xiocb.xiocb_psize = sizeof(struct xiocb_meminfo);
- xiocb.plist.xiocb_meminfo.mi_idx = idx;
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- *start = xiocb.plist.xiocb_meminfo.mi_addr;
- *length = xiocb.plist.xiocb_meminfo.mi_size;
- *type = xiocb.plist.xiocb_meminfo.mi_type;
- return 0;
- }
- int cfe_exit(int warm, int status)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_exitstat);
- xiocb.plist.xiocb_exitstat.status = status;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int cfe_flushcache(int flg)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = flg;
- xiocb.xiocb_psize = 0;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int cfe_getdevinfo(char *name)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
- xiocb.plist.xiocb_buffer.buf_offset = 0;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_buffer.buf_length = strlen(name);
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
- }
- int cfe_getenv(char *name, char *dest, int destlen)
- {
- struct cfe_xiocb xiocb;
- *dest = 0;
- xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
- xiocb.plist.xiocb_envbuf.enum_idx = 0;
- xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_envbuf.name_length = strlen(name);
- xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
- xiocb.plist.xiocb_envbuf.val_length = destlen;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int cfe_getfwinfo(cfe_fwinfo_t * info)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo);
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
- info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
- info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
- info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
- info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
- info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
- info->fwi_bootarea_size =
- xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
- return 0;
- }
- int cfe_getstdhandle(int flg)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = flg;
- xiocb.xiocb_psize = 0;
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.xiocb_handle;
- }
- int64_t
- cfe_getticks(void)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_time);
- xiocb.plist.xiocb_time.ticks = 0;
- cfe_iocb_dispatch(&xiocb);
- return xiocb.plist.xiocb_time.ticks;
- }
- int cfe_inpstat(int handle)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_inpstat);
- xiocb.plist.xiocb_inpstat.inp_status = 0;
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_inpstat.inp_status;
- }
- int
- cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
- int length, int *retlen, u64 offset)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
- xiocb.plist.xiocb_buffer.buf_offset = offset;
- xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
- xiocb.plist.xiocb_buffer.buf_length = length;
- cfe_iocb_dispatch(&xiocb);
- if (retlen)
- *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
- return xiocb.xiocb_status;
- }
- int cfe_open(char *name)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
- xiocb.plist.xiocb_buffer.buf_offset = 0;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_buffer.buf_length = strlen(name);
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.xiocb_handle;
- }
- int cfe_read(int handle, unsigned char *buffer, int length)
- {
- return cfe_readblk(handle, 0, buffer, length);
- }
- int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
- xiocb.plist.xiocb_buffer.buf_offset = offset;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
- xiocb.plist.xiocb_buffer.buf_length = length;
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_buffer.buf_retlen;
- }
- int cfe_setenv(char *name, char *val)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
- xiocb.plist.xiocb_envbuf.enum_idx = 0;
- xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_envbuf.name_length = strlen(name);
- xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
- xiocb.plist.xiocb_envbuf.val_length = strlen(val);
- cfe_iocb_dispatch(&xiocb);
- return xiocb.xiocb_status;
- }
- int cfe_write(int handle, const char *buffer, int length)
- {
- return cfe_writeblk(handle, 0, buffer, length);
- }
- int cfe_writeblk(int handle, s64 offset, const char *buffer, int length)
- {
- struct cfe_xiocb xiocb;
- xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
- xiocb.plist.xiocb_buffer.buf_offset = offset;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
- xiocb.plist.xiocb_buffer.buf_length = length;
- cfe_iocb_dispatch(&xiocb);
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_buffer.buf_retlen;
- }
- void __init cfe_die(char *fmt, ...)
- {
- unsigned int prid, __maybe_unused rev;
- char msg[128];
- va_list ap;
- int handle;
- unsigned int count;
- va_start(ap, fmt);
- vsprintf(msg, fmt, ap);
- strcat(msg, "\r\n");
- if (cfe_seal != CFE_EPTSEAL)
- goto no_cfe;
- prid = read_c0_prid();
- if ((prid & PRID_COMP_MASK) != PRID_COMP_BROADCOM)
- goto no_cfe;
- rev = prid & PRID_REV_MASK;
- /* disable XKS01 so that CFE can access the registers */
- switch (prid & PRID_IMP_MASK) {
- #ifdef CONFIG_CPU_BMIPS4380
- case PRID_IMP_BMIPS43XX:
- if (rev >= PRID_REV_BMIPS4380_LO &&
- rev <= PRID_REV_BMIPS4380_HI)
- __write_32bit_c0_register($22, 3,
- __read_32bit_c0_register($22, 3) & ~BIT(12));
- break;
- #endif
- #ifdef CONFIG_CPU_BMIPS5000
- case PRID_IMP_BMIPS5000:
- case PRID_IMP_BMIPS5200:
- __write_32bit_c0_register($22, 5,
- __read_32bit_c0_register($22, 5) & ~BIT(8));
- break;
- #endif
- default:
- break;
- }
- handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
- if (handle < 0)
- goto no_cfe;
- cfe_write(handle, msg, strlen(msg));
- for (count = 0; count < 0x7fffffff; count++)
- mb();
- cfe_exit(0, 1);
- while (1)
- ;
- no_cfe:
- /* probably won't print anywhere useful */
- panic("%s", msg);
- va_end(ap);
- }
|