linux/arch/mips/fw/cfe/cfe_api.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
   4 */
   5
   6/*
   7 *
   8 * Broadcom Common Firmware Environment (CFE)
   9 *
  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.
  13 *
  14 * Authors:  Mitch Lichtenberg, Chris Demetriou
  15 */
  16
  17#include <asm/fw/cfe/cfe_api.h>
  18#include "cfe_api_int.h"
  19
  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))
  23
  24int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
  25
  26/*
  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.
  33 */
  34
  35static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
  36static u64 cfe_handle;
  37
  38int cfe_init(u64 handle, u64 ept)
  39{
  40        cfe_dispfunc = NATIVE_FROM_XPTR(ept);
  41        cfe_handle = handle;
  42        return 0;
  43}
  44
  45int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
  46{
  47        if (!cfe_dispfunc)
  48                return -1;
  49        return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
  50}
  51
  52int cfe_close(int handle)
  53{
  54        struct cfe_xiocb xiocb;
  55
  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;
  61
  62        cfe_iocb_dispatch(&xiocb);
  63
  64        return xiocb.xiocb_status;
  65
  66}
  67
  68int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
  69{
  70        struct cfe_xiocb xiocb;
  71
  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;
  83
  84        cfe_iocb_dispatch(&xiocb);
  85
  86        return xiocb.xiocb_status;
  87}
  88
  89int cfe_cpu_stop(int cpu)
  90{
  91        struct cfe_xiocb xiocb;
  92
  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;
 100
 101        cfe_iocb_dispatch(&xiocb);
 102
 103        return xiocb.xiocb_status;
 104}
 105
 106int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
 107{
 108        struct cfe_xiocb xiocb;
 109
 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;
 120
 121        cfe_iocb_dispatch(&xiocb);
 122
 123        return xiocb.xiocb_status;
 124}
 125
 126int
 127cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
 128{
 129        struct cfe_xiocb xiocb;
 130
 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;
 137
 138        cfe_iocb_dispatch(&xiocb);
 139
 140        if (xiocb.xiocb_status < 0)
 141                return xiocb.xiocb_status;
 142
 143        *start = xiocb.plist.xiocb_meminfo.mi_addr;
 144        *length = xiocb.plist.xiocb_meminfo.mi_size;
 145        *type = xiocb.plist.xiocb_meminfo.mi_type;
 146
 147        return 0;
 148}
 149
 150int cfe_exit(int warm, int status)
 151{
 152        struct cfe_xiocb xiocb;
 153
 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;
 160
 161        cfe_iocb_dispatch(&xiocb);
 162
 163        return xiocb.xiocb_status;
 164}
 165
 166int cfe_flushcache(int flg)
 167{
 168        struct cfe_xiocb xiocb;
 169
 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;
 175
 176        cfe_iocb_dispatch(&xiocb);
 177
 178        return xiocb.xiocb_status;
 179}
 180
 181int cfe_getdevinfo(char *name)
 182{
 183        struct cfe_xiocb xiocb;
 184
 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);
 193
 194        cfe_iocb_dispatch(&xiocb);
 195
 196        if (xiocb.xiocb_status < 0)
 197                return xiocb.xiocb_status;
 198        return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
 199}
 200
 201int cfe_getenv(char *name, char *dest, int destlen)
 202{
 203        struct cfe_xiocb xiocb;
 204
 205        *dest = 0;
 206
 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;
 217
 218        cfe_iocb_dispatch(&xiocb);
 219
 220        return xiocb.xiocb_status;
 221}
 222
 223int cfe_getfwinfo(cfe_fwinfo_t * info)
 224{
 225        struct cfe_xiocb xiocb;
 226
 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);
 232
 233        cfe_iocb_dispatch(&xiocb);
 234
 235        if (xiocb.xiocb_status < 0)
 236                return xiocb.xiocb_status;
 237
 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;
 246#if 0
 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;
 250#endif
 251
 252        return 0;
 253}
 254
 255int cfe_getstdhandle(int flg)
 256{
 257        struct cfe_xiocb xiocb;
 258
 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;
 264
 265        cfe_iocb_dispatch(&xiocb);
 266
 267        if (xiocb.xiocb_status < 0)
 268                return xiocb.xiocb_status;
 269        return xiocb.xiocb_handle;
 270}
 271
 272int64_t
 273cfe_getticks(void)
 274{
 275        struct cfe_xiocb xiocb;
 276
 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;
 283
 284        cfe_iocb_dispatch(&xiocb);
 285
 286        return xiocb.plist.xiocb_time.ticks;
 287
 288}
 289
 290int cfe_inpstat(int handle)
 291{
 292        struct cfe_xiocb xiocb;
 293
 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;
 300
 301        cfe_iocb_dispatch(&xiocb);
 302
 303        if (xiocb.xiocb_status < 0)
 304                return xiocb.xiocb_status;
 305        return xiocb.plist.xiocb_inpstat.inp_status;
 306}
 307
 308int
 309cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
 310          int length, int *retlen, u64 offset)
 311{
 312        struct cfe_xiocb xiocb;
 313
 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;
 323
 324        cfe_iocb_dispatch(&xiocb);
 325
 326        if (retlen)
 327                *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
 328        return xiocb.xiocb_status;
 329}
 330
 331int cfe_open(char *name)
 332{
 333        struct cfe_xiocb xiocb;
 334
 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);
 343
 344        cfe_iocb_dispatch(&xiocb);
 345
 346        if (xiocb.xiocb_status < 0)
 347                return xiocb.xiocb_status;
 348        return xiocb.xiocb_handle;
 349}
 350
 351int cfe_read(int handle, unsigned char *buffer, int length)
 352{
 353        return cfe_readblk(handle, 0, buffer, length);
 354}
 355
 356int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
 357{
 358        struct cfe_xiocb xiocb;
 359
 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;
 368
 369        cfe_iocb_dispatch(&xiocb);
 370
 371        if (xiocb.xiocb_status < 0)
 372                return xiocb.xiocb_status;
 373        return xiocb.plist.xiocb_buffer.buf_retlen;
 374}
 375
 376int cfe_setenv(char *name, char *val)
 377{
 378        struct cfe_xiocb xiocb;
 379
 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);
 390
 391        cfe_iocb_dispatch(&xiocb);
 392
 393        return xiocb.xiocb_status;
 394}
 395
 396int cfe_write(int handle, const char *buffer, int length)
 397{
 398        return cfe_writeblk(handle, 0, buffer, length);
 399}
 400
 401int cfe_writeblk(int handle, s64 offset, const char *buffer, int length)
 402{
 403        struct cfe_xiocb xiocb;
 404
 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;
 413
 414        cfe_iocb_dispatch(&xiocb);
 415
 416        if (xiocb.xiocb_status < 0)
 417                return xiocb.xiocb_status;
 418        return xiocb.plist.xiocb_buffer.buf_retlen;
 419}
 420