0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/init.h>
0017 #include <linux/kernel.h>
0018 #include <linux/printk.h>
0019 #include <asm/mipsregs.h>
0020 #include <asm/fw/cfe/cfe_api.h>
0021 #include "cfe_api_int.h"
0022
0023 unsigned long __initdata cfe_seal;
0024
0025
0026 #define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
0027 #define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
0028
0029 int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
0041 static u64 cfe_handle;
0042
0043 int cfe_init(u64 handle, u64 ept)
0044 {
0045 cfe_dispfunc = NATIVE_FROM_XPTR(ept);
0046 cfe_handle = handle;
0047 return 0;
0048 }
0049
0050 int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
0051 {
0052 if (!cfe_dispfunc)
0053 return -1;
0054 return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
0055 }
0056
0057 int cfe_close(int handle)
0058 {
0059 struct cfe_xiocb xiocb;
0060
0061 xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
0062 xiocb.xiocb_status = 0;
0063 xiocb.xiocb_handle = handle;
0064 xiocb.xiocb_flags = 0;
0065 xiocb.xiocb_psize = 0;
0066
0067 cfe_iocb_dispatch(&xiocb);
0068
0069 return xiocb.xiocb_status;
0070
0071 }
0072
0073 int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
0074 {
0075 struct cfe_xiocb xiocb;
0076
0077 xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
0078 xiocb.xiocb_status = 0;
0079 xiocb.xiocb_handle = 0;
0080 xiocb.xiocb_flags = 0;
0081 xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
0082 xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
0083 xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
0084 xiocb.plist.xiocb_cpuctl.gp_val = gp;
0085 xiocb.plist.xiocb_cpuctl.sp_val = sp;
0086 xiocb.plist.xiocb_cpuctl.a1_val = a1;
0087 xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
0088
0089 cfe_iocb_dispatch(&xiocb);
0090
0091 return xiocb.xiocb_status;
0092 }
0093
0094 int cfe_cpu_stop(int cpu)
0095 {
0096 struct cfe_xiocb xiocb;
0097
0098 xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
0099 xiocb.xiocb_status = 0;
0100 xiocb.xiocb_handle = 0;
0101 xiocb.xiocb_flags = 0;
0102 xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
0103 xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
0104 xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
0105
0106 cfe_iocb_dispatch(&xiocb);
0107
0108 return xiocb.xiocb_status;
0109 }
0110
0111 int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
0112 {
0113 struct cfe_xiocb xiocb;
0114
0115 xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
0116 xiocb.xiocb_status = 0;
0117 xiocb.xiocb_handle = 0;
0118 xiocb.xiocb_flags = 0;
0119 xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
0120 xiocb.plist.xiocb_envbuf.enum_idx = idx;
0121 xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
0122 xiocb.plist.xiocb_envbuf.name_length = namelen;
0123 xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
0124 xiocb.plist.xiocb_envbuf.val_length = vallen;
0125
0126 cfe_iocb_dispatch(&xiocb);
0127
0128 return xiocb.xiocb_status;
0129 }
0130
0131 int
0132 cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
0133 {
0134 struct cfe_xiocb xiocb;
0135
0136 xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
0137 xiocb.xiocb_status = 0;
0138 xiocb.xiocb_handle = 0;
0139 xiocb.xiocb_flags = flags;
0140 xiocb.xiocb_psize = sizeof(struct xiocb_meminfo);
0141 xiocb.plist.xiocb_meminfo.mi_idx = idx;
0142
0143 cfe_iocb_dispatch(&xiocb);
0144
0145 if (xiocb.xiocb_status < 0)
0146 return xiocb.xiocb_status;
0147
0148 *start = xiocb.plist.xiocb_meminfo.mi_addr;
0149 *length = xiocb.plist.xiocb_meminfo.mi_size;
0150 *type = xiocb.plist.xiocb_meminfo.mi_type;
0151
0152 return 0;
0153 }
0154
0155 int cfe_exit(int warm, int status)
0156 {
0157 struct cfe_xiocb xiocb;
0158
0159 xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
0160 xiocb.xiocb_status = 0;
0161 xiocb.xiocb_handle = 0;
0162 xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
0163 xiocb.xiocb_psize = sizeof(struct xiocb_exitstat);
0164 xiocb.plist.xiocb_exitstat.status = status;
0165
0166 cfe_iocb_dispatch(&xiocb);
0167
0168 return xiocb.xiocb_status;
0169 }
0170
0171 int cfe_flushcache(int flg)
0172 {
0173 struct cfe_xiocb xiocb;
0174
0175 xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
0176 xiocb.xiocb_status = 0;
0177 xiocb.xiocb_handle = 0;
0178 xiocb.xiocb_flags = flg;
0179 xiocb.xiocb_psize = 0;
0180
0181 cfe_iocb_dispatch(&xiocb);
0182
0183 return xiocb.xiocb_status;
0184 }
0185
0186 int cfe_getdevinfo(char *name)
0187 {
0188 struct cfe_xiocb xiocb;
0189
0190 xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
0191 xiocb.xiocb_status = 0;
0192 xiocb.xiocb_handle = 0;
0193 xiocb.xiocb_flags = 0;
0194 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
0195 xiocb.plist.xiocb_buffer.buf_offset = 0;
0196 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
0197 xiocb.plist.xiocb_buffer.buf_length = strlen(name);
0198
0199 cfe_iocb_dispatch(&xiocb);
0200
0201 if (xiocb.xiocb_status < 0)
0202 return xiocb.xiocb_status;
0203 return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
0204 }
0205
0206 int cfe_getenv(char *name, char *dest, int destlen)
0207 {
0208 struct cfe_xiocb xiocb;
0209
0210 *dest = 0;
0211
0212 xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
0213 xiocb.xiocb_status = 0;
0214 xiocb.xiocb_handle = 0;
0215 xiocb.xiocb_flags = 0;
0216 xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
0217 xiocb.plist.xiocb_envbuf.enum_idx = 0;
0218 xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
0219 xiocb.plist.xiocb_envbuf.name_length = strlen(name);
0220 xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
0221 xiocb.plist.xiocb_envbuf.val_length = destlen;
0222
0223 cfe_iocb_dispatch(&xiocb);
0224
0225 return xiocb.xiocb_status;
0226 }
0227
0228 int cfe_getfwinfo(cfe_fwinfo_t * info)
0229 {
0230 struct cfe_xiocb xiocb;
0231
0232 xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
0233 xiocb.xiocb_status = 0;
0234 xiocb.xiocb_handle = 0;
0235 xiocb.xiocb_flags = 0;
0236 xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo);
0237
0238 cfe_iocb_dispatch(&xiocb);
0239
0240 if (xiocb.xiocb_status < 0)
0241 return xiocb.xiocb_status;
0242
0243 info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
0244 info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
0245 info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
0246 info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
0247 info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
0248 info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
0249 info->fwi_bootarea_size =
0250 xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
0251
0252 return 0;
0253 }
0254
0255 int cfe_getstdhandle(int flg)
0256 {
0257 struct cfe_xiocb xiocb;
0258
0259 xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
0260 xiocb.xiocb_status = 0;
0261 xiocb.xiocb_handle = 0;
0262 xiocb.xiocb_flags = flg;
0263 xiocb.xiocb_psize = 0;
0264
0265 cfe_iocb_dispatch(&xiocb);
0266
0267 if (xiocb.xiocb_status < 0)
0268 return xiocb.xiocb_status;
0269 return xiocb.xiocb_handle;
0270 }
0271
0272 int64_t
0273 cfe_getticks(void)
0274 {
0275 struct cfe_xiocb xiocb;
0276
0277 xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
0278 xiocb.xiocb_status = 0;
0279 xiocb.xiocb_handle = 0;
0280 xiocb.xiocb_flags = 0;
0281 xiocb.xiocb_psize = sizeof(struct xiocb_time);
0282 xiocb.plist.xiocb_time.ticks = 0;
0283
0284 cfe_iocb_dispatch(&xiocb);
0285
0286 return xiocb.plist.xiocb_time.ticks;
0287
0288 }
0289
0290 int cfe_inpstat(int handle)
0291 {
0292 struct cfe_xiocb xiocb;
0293
0294 xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
0295 xiocb.xiocb_status = 0;
0296 xiocb.xiocb_handle = handle;
0297 xiocb.xiocb_flags = 0;
0298 xiocb.xiocb_psize = sizeof(struct xiocb_inpstat);
0299 xiocb.plist.xiocb_inpstat.inp_status = 0;
0300
0301 cfe_iocb_dispatch(&xiocb);
0302
0303 if (xiocb.xiocb_status < 0)
0304 return xiocb.xiocb_status;
0305 return xiocb.plist.xiocb_inpstat.inp_status;
0306 }
0307
0308 int
0309 cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
0310 int length, int *retlen, u64 offset)
0311 {
0312 struct cfe_xiocb xiocb;
0313
0314 xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
0315 xiocb.xiocb_status = 0;
0316 xiocb.xiocb_handle = handle;
0317 xiocb.xiocb_flags = 0;
0318 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
0319 xiocb.plist.xiocb_buffer.buf_offset = offset;
0320 xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
0321 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
0322 xiocb.plist.xiocb_buffer.buf_length = length;
0323
0324 cfe_iocb_dispatch(&xiocb);
0325
0326 if (retlen)
0327 *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
0328 return xiocb.xiocb_status;
0329 }
0330
0331 int cfe_open(char *name)
0332 {
0333 struct cfe_xiocb xiocb;
0334
0335 xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
0336 xiocb.xiocb_status = 0;
0337 xiocb.xiocb_handle = 0;
0338 xiocb.xiocb_flags = 0;
0339 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
0340 xiocb.plist.xiocb_buffer.buf_offset = 0;
0341 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
0342 xiocb.plist.xiocb_buffer.buf_length = strlen(name);
0343
0344 cfe_iocb_dispatch(&xiocb);
0345
0346 if (xiocb.xiocb_status < 0)
0347 return xiocb.xiocb_status;
0348 return xiocb.xiocb_handle;
0349 }
0350
0351 int cfe_read(int handle, unsigned char *buffer, int length)
0352 {
0353 return cfe_readblk(handle, 0, buffer, length);
0354 }
0355
0356 int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
0357 {
0358 struct cfe_xiocb xiocb;
0359
0360 xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
0361 xiocb.xiocb_status = 0;
0362 xiocb.xiocb_handle = handle;
0363 xiocb.xiocb_flags = 0;
0364 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
0365 xiocb.plist.xiocb_buffer.buf_offset = offset;
0366 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
0367 xiocb.plist.xiocb_buffer.buf_length = length;
0368
0369 cfe_iocb_dispatch(&xiocb);
0370
0371 if (xiocb.xiocb_status < 0)
0372 return xiocb.xiocb_status;
0373 return xiocb.plist.xiocb_buffer.buf_retlen;
0374 }
0375
0376 int cfe_setenv(char *name, char *val)
0377 {
0378 struct cfe_xiocb xiocb;
0379
0380 xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
0381 xiocb.xiocb_status = 0;
0382 xiocb.xiocb_handle = 0;
0383 xiocb.xiocb_flags = 0;
0384 xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
0385 xiocb.plist.xiocb_envbuf.enum_idx = 0;
0386 xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
0387 xiocb.plist.xiocb_envbuf.name_length = strlen(name);
0388 xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
0389 xiocb.plist.xiocb_envbuf.val_length = strlen(val);
0390
0391 cfe_iocb_dispatch(&xiocb);
0392
0393 return xiocb.xiocb_status;
0394 }
0395
0396 int cfe_write(int handle, const char *buffer, int length)
0397 {
0398 return cfe_writeblk(handle, 0, buffer, length);
0399 }
0400
0401 int cfe_writeblk(int handle, s64 offset, const char *buffer, int length)
0402 {
0403 struct cfe_xiocb xiocb;
0404
0405 xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
0406 xiocb.xiocb_status = 0;
0407 xiocb.xiocb_handle = handle;
0408 xiocb.xiocb_flags = 0;
0409 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
0410 xiocb.plist.xiocb_buffer.buf_offset = offset;
0411 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
0412 xiocb.plist.xiocb_buffer.buf_length = length;
0413
0414 cfe_iocb_dispatch(&xiocb);
0415
0416 if (xiocb.xiocb_status < 0)
0417 return xiocb.xiocb_status;
0418 return xiocb.plist.xiocb_buffer.buf_retlen;
0419 }
0420
0421 void __init cfe_die(char *fmt, ...)
0422 {
0423 unsigned int prid, __maybe_unused rev;
0424 char msg[128];
0425 va_list ap;
0426 int handle;
0427 unsigned int count;
0428
0429 va_start(ap, fmt);
0430 vsprintf(msg, fmt, ap);
0431 strcat(msg, "\r\n");
0432
0433 if (cfe_seal != CFE_EPTSEAL)
0434 goto no_cfe;
0435
0436 prid = read_c0_prid();
0437 if ((prid & PRID_COMP_MASK) != PRID_COMP_BROADCOM)
0438 goto no_cfe;
0439
0440 rev = prid & PRID_REV_MASK;
0441
0442
0443 switch (prid & PRID_IMP_MASK) {
0444 #ifdef CONFIG_CPU_BMIPS4380
0445 case PRID_IMP_BMIPS43XX:
0446 if (rev >= PRID_REV_BMIPS4380_LO &&
0447 rev <= PRID_REV_BMIPS4380_HI)
0448 __write_32bit_c0_register($22, 3,
0449 __read_32bit_c0_register($22, 3) & ~BIT(12));
0450 break;
0451 #endif
0452 #ifdef CONFIG_CPU_BMIPS5000
0453 case PRID_IMP_BMIPS5000:
0454 case PRID_IMP_BMIPS5200:
0455 __write_32bit_c0_register($22, 5,
0456 __read_32bit_c0_register($22, 5) & ~BIT(8));
0457 break;
0458 #endif
0459 default:
0460 break;
0461 }
0462
0463 handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
0464 if (handle < 0)
0465 goto no_cfe;
0466
0467 cfe_write(handle, msg, strlen(msg));
0468
0469 for (count = 0; count < 0x7fffffff; count++)
0470 mb();
0471 cfe_exit(0, 1);
0472 while (1)
0473 ;
0474
0475 no_cfe:
0476
0477 panic("%s", msg);
0478
0479 va_end(ap);
0480 }