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
 247        return 0;
 248}
 249
 250int cfe_getstdhandle(int flg)
 251{
 252        struct cfe_xiocb xiocb;
 253
 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;
 259
 260        cfe_iocb_dispatch(&xiocb);
 261
 262        if (xiocb.xiocb_status < 0)
 263                return xiocb.xiocb_status;
 264        return xiocb.xiocb_handle;
 265}
 266
 267int64_t
 268cfe_getticks(void)
 269{
 270        struct cfe_xiocb xiocb;
 271
 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;
 278
 279        cfe_iocb_dispatch(&xiocb);
 280
 281        return xiocb.plist.xiocb_time.ticks;
 282
 283}
 284
 285int cfe_inpstat(int handle)
 286{
 287        struct cfe_xiocb xiocb;
 288
 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;
 295
 296        cfe_iocb_dispatch(&xiocb);
 297
 298        if (xiocb.xiocb_status < 0)
 299                return xiocb.xiocb_status;
 300        return xiocb.plist.xiocb_inpstat.inp_status;
 301}
 302
 303int
 304cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
 305          int length, int *retlen, u64 offset)
 306{
 307        struct cfe_xiocb xiocb;
 308
 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;
 318
 319        cfe_iocb_dispatch(&xiocb);
 320
 321        if (retlen)
 322                *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
 323        return xiocb.xiocb_status;
 324}
 325
 326int cfe_open(char *name)
 327{
 328        struct cfe_xiocb xiocb;
 329
 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);
 338
 339        cfe_iocb_dispatch(&xiocb);
 340
 341        if (xiocb.xiocb_status < 0)
 342                return xiocb.xiocb_status;
 343        return xiocb.xiocb_handle;
 344}
 345
 346int cfe_read(int handle, unsigned char *buffer, int length)
 347{
 348        return cfe_readblk(handle, 0, buffer, length);
 349}
 350
 351int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
 352{
 353        struct cfe_xiocb xiocb;
 354
 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;
 363
 364        cfe_iocb_dispatch(&xiocb);
 365
 366        if (xiocb.xiocb_status < 0)
 367                return xiocb.xiocb_status;
 368        return xiocb.plist.xiocb_buffer.buf_retlen;
 369}
 370
 371int cfe_setenv(char *name, char *val)
 372{
 373        struct cfe_xiocb xiocb;
 374
 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);
 385
 386        cfe_iocb_dispatch(&xiocb);
 387
 388        return xiocb.xiocb_status;
 389}
 390
 391int cfe_write(int handle, const char *buffer, int length)
 392{
 393        return cfe_writeblk(handle, 0, buffer, length);
 394}
 395
 396int cfe_writeblk(int handle, s64 offset, const char *buffer, int length)
 397{
 398        struct cfe_xiocb xiocb;
 399
 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;
 408
 409        cfe_iocb_dispatch(&xiocb);
 410
 411        if (xiocb.xiocb_status < 0)
 412                return xiocb.xiocb_status;
 413        return xiocb.plist.xiocb_buffer.buf_retlen;
 414}
 415