/********************************************************************************
*	File : reset.S
*	Author : Alain Greiner
*	Date : 15/01/2014
*********************************************************************************
* This is a boot code for a generic multi-clusters / multi-processors
* TSAR architecture (up to 256 clusters / up to 4  processors per cluster). 
* The physical address is 40 bits, and the 8 MSB bits A[39:32] define the
* cluster index.
*
* As we don't want to use the virtual memory, the physical address is 
* equal to  the virtual address (identity mapping) and all processors use
* the physical memory bank in cluster 0. Both the reset base address and 
* the kernel base address can be redefined to use a physical memory bank
* smaller than 4 Gbytes.
*
* There is one XCU iand one MMC per cluster.
* All other peripherals (including the boot ROM) are located in cluster 0.
* Only two HWI interrupts are supported:
* - IRQ_IN[0]      IOC 
* - IRQ_IN[12]     MMC
*
* The boot sequence is the following:
*   - Each processor initializes the stack pointer ($29) depending on proc_id.
*   - Each processor initializes the CP0 EBASE register
*	- Only processor 0 initializes the Interrupt vector.
*   - Each processor initializes its private XCU mask.
*	- Each processor initializes the Status Register (SR) 
*	- Each processor jumps to the same main address in kernel mode...
********************************************************************************/

#include "hard_config.h"
#include "mips32_registers.h"

	.section .reset,"ax",@progbits

	.extern	seg_stack_base
	.extern	seg_xcu_base
    .extern seg_kcode_base
	.extern _interrupt_vector
	.extern _ioc_isr
	.extern _mmc_isr
    .extern main

	.globl  reset	 			
	.ent	reset
	.align	2

reset:
       	.set noreorder

/* each proc computes  proc_id, lpid, cluster_xy */
    mfc0    $26,    CP0_PROCID
    andi    $26,    $26,    0x3FF	    /* at most 1024 processors */
    move    $10,    $26                 /* $10 <= proc_id  */
    li      $27,    NB_PROCS_MAX
    divu    $26,    $27
    mfhi    $11                         /* $11 <= lpid */
    mflo    $12                         /* $12 <= cluster_xy */

/* each proc initializes stack pointer (64K per processor) */
    la      $27,    seg_stack_base
    addi    $26,    $10,    1		    /* $26 <= (proc_id + 1)           */
    sll     $26,    $26,    16          /* $26 <= (proc_id + 1) * 64K     */
    addu    $29,    $27,    $26		    /* $29 <= seg_stack_base(proc_id) */

/* each proc initializes CP0 EBASE register */
    la      $26,    seg_kcode_base
    mtc0    $26,    CP0_EBASE           /* CP0_EBASE <= seg_kcode_base */

/* only proc (0,0,0) initializes interrupt vector */
    bne	    $10,    $0,    reset_xcu
    nop

    la      $26,    _interrupt_vector   /* interrupt vector address */
    la      $27,    _ioc_isr 
    sw      $27,     0($26)             /* interrupt_vector[0] <= _isr_ioc */
    la      $27,    _mmc_isr 
    sw      $27,     48($26)            /* interrupt_vector[12] <= _isr_mmc */
    
reset_xcu:

/* only proc (x,y,0) receive IRQs and initialise its private XCU mask */
    bne     $11,    $0,     reset_end
    nop
    la      $26,    seg_xcu_base
    li      $27,    0b010010000000      /* offset for MSK_HWI_ENABLE & lpid == 0 */
    addu    $24,    $26,    $27         /* $24 <= &MASK  */
    li      $25,    0x00001001		    /* IOC: IRQ[0] / MEMC: IRQ[12] */
    sw      $25,    0($24)              /* set MASK */

reset_end:

/* initializes SR register */
    li	    $26,    0x0000FF01		
    mtc0    $26,    $12			        /* SR <= kernel mode / IRQ enable */

/* jumps to main in kernel mode */
    la	    $26,    main
    jr      $26
    nop

    .end	reset

    .set reorder
