1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * API entry module File: apientry.S 5 * 6 * Low-level API entry point routines and some other misc stuff. 7 * 8 * Author: Mitch Lichtenberg (mpl@broadcom.com) 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 15 * This software is furnished under license and may be used and 16 * copied only in accordance with the following terms and 17 * conditions. Subject to these conditions, you may download, 18 * copy, install, use, modify and distribute modified or unmodified 19 * copies of this software in source and/or binary form. No title 20 * or ownership is transferred hereby. 21 * 22 * 1) Any source code used, modified or distributed must reproduce 23 * and retain this copyright notice and list of conditions 24 * as they appear in the source file. 25 * 26 * 2) No right is granted to use any trade name, trademark, or 27 * logo of Broadcom Corporation. The "Broadcom Corporation" 28 * name may not be used to endorse or promote products derived 29 * from this software without the prior written permission of 30 * Broadcom Corporation. 31 * 32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 44 * THE POSSIBILITY OF SUCH DAMAGE. 45 ********************************************************************* */ 46 47 48#include "sbmips.h" 49#include "exception.h" 50 51#include "bsp_config.h" 52#include "cpu_config.h" 53 54#ifdef _CFE_ 55#include "cfe_devfuncs.h" 56#else 57 58#if (CFG_BIENDIAN) && defined(__MIPSEB) 59#define CFE_EPTSEAL_REV 0x31454643 60#endif 61#define CFE_EPTSEAL 0x43464531 62 63#define cfe_command_restart 0 64#endif 65 66#ifndef CFG_STACK_SIZE 67#error "CFG_STACK_SIZE not defined" 68#else 69#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) 70#endif 71 72#include "segtable.h" 73 74#if defined(_ZIPSTART_) 75#error "This should not be part of zipstart." 76#endif 77 78/* ********************************************************************* 79 * Macros 80 ********************************************************************* */ 81 82#include "mipsmacros.h" 83 84/* ********************************************************************* 85 * Data 86 ********************************************************************* */ 87 88#if CFG_MULTI_CPUS 89 90 .sdata 91 .globl cfe_spinlock 92cfe_spinlock: .word 0 93#endif 94 95 96/* ********************************************************************* 97 * Code starts here 98 ********************************************************************* */ 99 100 101 .text 102 103 104/* ********************************************************************* 105 * cpu_apientry(handle,iocb) 106 * 107 * API entry point for external apps. 108 * 109 * Input parameters: 110 * a0 - firmware handle (used to determine the location of 111 * our relocated data) 112 * a1 - pointer to IOCB to execute 113 * 114 * Return value: 115 * v0 - return code, 0 if ok 116 ********************************************************************* */ 117 118#define _regidx(x) ((x)*8) 119 120#define CAE_SRSAVE _regidx(0) 121#define CAE_GPSAVE _regidx(1) 122#define CAE_RASAVE _regidx(2) 123#define CAE_S0SAVE _regidx(3) 124#define CAE_S1SAVE _regidx(4) 125#define CAE_S2SAVE _regidx(5) 126#define CAE_S3SAVE _regidx(6) 127#define CAE_S4SAVE _regidx(7) 128#define CAE_S5SAVE _regidx(8) 129#define CAE_S6SAVE _regidx(9) 130#define CAE_S7SAVE _regidx(10) 131#define CAE_K0SAVE _regidx(11) 132#define CAE_K1SAVE _regidx(12) 133 134#define CAE_STKSIZE _regidx(14) 135 136#if defined(__MIPSEB) 137#define ENDIANOFFSET 4 138#else 139#define ENDIANOFFSET 0 140#endif 141 142#define R_XIOCB_FCODE (8*0+ENDIANOFFSET) 143#define R_XIOCB_FLAGS (8*3+ENDIANOFFSET) 144#define R_XIOCB_XSTAT (8*5+ENDIANOFFSET) 145 146#define CFE_CMD_FW_RESTART 1 147#define CFE_FLG_WARMSTART 0x00000001 148 149LEAF(cpu_apientry) 150 151 /* 152 * Gross: Make an explicit check here for a warm firmware restart, 153 * to avoid setting up the stack and doing other nasty things 154 * when we're just going to return to the firmware anyway. 155 */ 156 157 lw t0,R_XIOCB_FCODE(a1) 158 bne t0,CFE_CMD_FW_RESTART,notwarm 159 lw t0,R_XIOCB_FLAGS(a1) 160 and t0,CFE_FLG_WARMSTART 161 bne t0,CFE_FLG_WARMSTART,notwarm 162 163 /* 164 * Disable interrupts before warm restart. Don't bother 165 * to save the results on the stack, we aren't going back. 166 */ 167 168 mfc0 t0,C0_SR # Get current interrupt flag 169 and t0,~M_SR_IE 170 mtc0 t0,C0_SR 171 HAZARD 172 173 /* 174 * Transfer control back to CFE, passing exit status. 175 */ 176 177 move gp,a0 # Reset our GP 178 lw a0,R_XIOCB_XSTAT(a1) # Exit status 179 b _cfe_warmstart 180 181 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 182 183 /* 184 * Not a warm restart, run on the caller's stack. 185 */ 186 187notwarm: sub sp,CAE_STKSIZE # Make room for our stuff 188 189 mfc0 v0,C0_SR # Get current interrupt flag 190 SREG v0,CAE_SRSAVE(sp) # save on stack 191 li t0,M_SR_IE # master interrupt control 192 not t0 # disable interrupts 193 and v0,t0 # SR now has IE=0 194#if CPUCFG_REGS64 195 or v0,M_SR_KX 196#endif 197 mtc0 v0,C0_SR # put back into CP0 198 HAZARD 199 200 SREG gp,CAE_GPSAVE(sp) # save GP 201 SREG ra,CAE_RASAVE(sp) # and old RA 202 203 SREG s0,CAE_S0SAVE(sp) 204 SREG s1,CAE_S1SAVE(sp) 205 SREG s2,CAE_S2SAVE(sp) 206 SREG s3,CAE_S3SAVE(sp) 207 SREG s4,CAE_S4SAVE(sp) 208 SREG s5,CAE_S5SAVE(sp) 209 SREG s6,CAE_S6SAVE(sp) 210 SREG s7,CAE_S7SAVE(sp) 211 SREG k0,CAE_K0SAVE(sp) 212 SREG k1,CAE_K1SAVE(sp) 213 214 move gp,a0 # set up new GP 215 move a0,a1 # A0 points at IOCB 216 217#if CFG_MULTI_CPUS 218 SPIN_LOCK(cfe_spinlock,t0,t1) 219#endif 220 221 JAL(cfe_doxreq) 222 223#if CFG_MULTI_CPUS 224 SPIN_UNLOCK(cfe_spinlock,t0) 225#endif 226 227 # 228 # Restore the saved registers. 229 # 230 231 LREG k1,CAE_K1SAVE(sp) 232 LREG k0,CAE_K0SAVE(sp) 233 LREG s7,CAE_S7SAVE(sp) 234 LREG s6,CAE_S6SAVE(sp) 235 LREG s5,CAE_S5SAVE(sp) 236 LREG s4,CAE_S4SAVE(sp) 237 LREG s3,CAE_S3SAVE(sp) 238 LREG s2,CAE_S2SAVE(sp) 239 LREG s1,CAE_S1SAVE(sp) 240 LREG s0,CAE_S0SAVE(sp) 241 242 LREG ra,CAE_RASAVE(sp) # unwind the stack 243 LREG gp,CAE_GPSAVE(sp) 244 245 LREG t0,CAE_SRSAVE(sp) # old interrupt mask 246 247 add sp,CAE_STKSIZE # restore old stack pointer 248 249 mtc0 t0,C0_SR # restore interrupts 250 HAZARD 251 j ra 252 nop 253END(cpu_apientry) 254 255 256 257/* ********************************************************************* 258 * CFE_WARMSTART 259 * 260 * Restart the command interpreter 261 * 262 * Input parameters: 263 * A0 - command status 264 * nothing (GP has already been set up for us) 265 * 266 * Return value: 267 * nothing 268 ********************************************************************* */ 269 270LEAF(cfe_warmstart) 271 272_cfe_warmstart: 273 /* 274 * Reset the stack pointer. 275 */ 276 277 LR sp,mem_heapstart 278 ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) 279 280 281 /* 282 * Undo any CP0 setup the calling program left behind. 283 */ 284 285 SR a0,0(sp) 286 JAL(CPUCFG_CPURESTART) 287 LR a0,0(sp) 288 289 /* 290 * If this is the 64-bit version, turn on the KX bit 291 * to allow 64-bit accesses. 292 */ 293 294#if CPUCFG_REGS64 295 mfc0 t0,C0_SR 296 or t0,t0,M_SR_KX 297 mtc0 t0,C0_SR 298 HAZARD 299#endif 300 301 302 303#ifdef notused 304 LR v0,cfe_pagetable # reestablish 305 dsll v0,v0,13 # see mips_arena.c for this 306 dmtc0 v0,C0_CTEXT # boot area TLBs 307 308 la t9,sb1_cp0_init 309 jalr t9 310#endif 311 312 /* 313 * If someone called the API to do a warm start, clear the 314 * spin lock, since the call will never return. 315 */ 316 317#if CFG_MULTI_CPUS 318 SPIN_UNLOCK(cfe_spinlock,t0) 319#endif 320 321 /* 322 * Switch back to using RAM vectors. 323 */ 324 325 mfc0 t0,C0_SR 326 and t0,t0,~M_SR_BEV 327 mtc0 t0,C0_SR 328 HAZARD 329 330 JAL(cfe_command_restart) 331 332END(cfe_warmstart) 333 334 335 336/* ********************************************************************* 337 * _GETSTATUS() 338 * 339 * Read the STATUS register into v0 340 * 341 * Input parameters: 342 * nothing 343 * 344 * Return value: 345 * v0 - Status register 346 ********************************************************************* */ 347 348LEAF(_getstatus) 349 350 mfc0 v0,C0_SR 351 j ra 352END(_getstatus) 353 354/* ********************************************************************* 355 * _SETSTATUS() 356 * 357 * Set the STATUS register to the value in a0 358 * 359 * Input parameters: 360 * nothing 361 * 362 * Return value: 363 * v0 - Status register 364 ********************************************************************* */ 365 366LEAF(_setstatus) 367 368 mtc0 a0,C0_SR 369 j ra 370END(_setstatus) 371 372 373/* ********************************************************************* 374 * _GETCAUSE() 375 * 376 * Read the CAUSE register into v0 377 * 378 * Input parameters: 379 * nothing 380 * 381 * Return value: 382 * v0 - Cause register 383 ********************************************************************* */ 384 385LEAF(_getcause) 386 387 mfc0 v0,C0_CAUSE 388 j ra 389END(_getcause) 390 391 392/* ********************************************************************* 393 * _GETTICKS() 394 * 395 * Read the COUNT register into v0 396 * 397 * Input parameters: 398 * nothing 399 * 400 * Return value: 401 * v0 - count register 402 ********************************************************************* */ 403 404LEAF(_getticks) 405 406 mfc0 v0,C0_COUNT 407 j ra 408END(_getticks) 409 410 411/* ********************************************************************* 412 * _SETALARM(ticks) 413 * 414 * Set the C0_Compare register from a0 415 * 416 * Input parameters: 417 * a0 - compare register 418 * 419 * Return value: 420 * none 421 ********************************************************************* */ 422 423LEAF(_setalarm) 424 425 mtc0 a0,C0_COMPARE 426 j ra 427END(_setalarm) 428 429 430/* ********************************************************************* 431 * _SETCONTEXT() 432 * 433 * Set the CONTEXT register. 434 * 435 * Input parameters: 436 * a0 - context 437 * 438 * Return value: 439 * nothing 440 ********************************************************************* */ 441 442LEAF(_setcontext) 443 444 MTC0 a0,C0_CTEXT 445 j ra 446END(_setcontext) 447 448/* ********************************************************************* 449 * _GETSEGTBL() 450 * 451 * Return the address of the segment table. We use this 452 * to display the startup messages. 453 * 454 * You can't just address the table from C because it lives 455 * in the text segment. 456 * 457 * Input parameters: 458 * nothing 459 * 460 * Return value: 461 * address of table 462 ********************************************************************* */ 463 464 465LEAF(_getsegtbl) 466 la v0,segment_table 467 j ra 468END(_getsegtbl) 469 470 471/* ********************************************************************* 472 * _wbflush() 473 * 474 * Flush the write buffer. This is probably not necessary 475 * on SiByte CPUs, but we have it for completeness. 476 * 477 * Input parameters: 478 * nothing 479 * 480 * Return value: 481 * nothing 482 ********************************************************************* */ 483 484LEAF(_wbflush) 485 486 sync /* drain the buffers */ 487 la t0,__junk /* do an uncached read to force it out */ 488 or t0,K1BASE 489 lw zero,0(t0) 490 j ra 491 492END(_wbflush) 493 494 495/* ********************************************************************* 496 * CFE_FLUSHCACHE 497 * 498 * Perform certain cache operations 499 * 500 * Input parameters: 501 * a0 - flags (CFE_CACHE_xxx flags, or zero for a default) 502 * a1,a2 - start/end of range for "range invalidate" operations 503 * (not used otherwise) 504 * 505 * Return value: 506 * nothing 507 ********************************************************************* */ 508 509LEAF(_cfe_flushcache) 510 511 sub sp,56 512 SREG ra,0(sp) 513 SREG a0,8(sp) 514 SREG s0,16(sp) 515 SREG v1,24(sp) 516 SREG s1,32(sp) 517 SREG s2,40(sp) 518 SREG s3,48(sp) 519 SREG s4,56(sp) 520 521 JAL(CPUCFG_CACHEOPS) 522 523 LREG s4,56(sp) 524 LREG s3,48(sp) 525 LREG s2,40(sp) 526 LREG s1,32(sp) 527 LREG v1,24(sp) 528 LREG s0,16(sp) 529 LREG a0,8(sp) 530 LREG ra,0(sp) 531 add sp,56 532 j ra 533 534END(_cfe_flushcache) 535 536 537/* ********************************************************************* 538 * End 539 ********************************************************************* */ 540