| 1 | /******************************************************************************** | 
|---|
| 2 | *   File : reset.S | 
|---|
| 3 | *   Author : Alain Greiner | 
|---|
| 4 | *   Date : 15/01/2014 | 
|---|
| 5 | ********************************************************************************* | 
|---|
| 6 | * This is a boot code for a generic multi-clusters / multi-processors | 
|---|
| 7 | * TSAR architecture (up to 256 clusters / up to 4  processors per cluster). | 
|---|
| 8 | * The physical address is 40 bits, and the 8 MSB bits A[39:32] define the | 
|---|
| 9 | * cluster index. | 
|---|
| 10 | * | 
|---|
| 11 | * As we don't want to use the virtual memory, the physical address is | 
|---|
| 12 | * equal to  the virtual address (identity mapping) and all processors stacks | 
|---|
| 13 | * and code segments are allocated in the physical memory bank in cluster 0. | 
|---|
| 14 | * | 
|---|
| 15 | * Both the reset base address and the kernel base address must be redefined | 
|---|
| 16 | * to use a physical memory bank smaller than 2 Gbytes. | 
|---|
| 17 | * | 
|---|
| 18 | * There is one XCU iand one MMC per cluster. | 
|---|
| 19 | * | 
|---|
| 20 | * There is one IOPIC component in cluster_io. | 
|---|
| 21 | * | 
|---|
| 22 | * There is two sets of peripherals: | 
|---|
| 23 | * | 
|---|
| 24 | * 1) A block device and a single channel TTY controller are available | 
|---|
| 25 | *    in cluster(0,0). | 
|---|
| 26 | * | 
|---|
| 27 | * 2) Other peripherals (including another Blockdevice, a multi-channels TTY | 
|---|
| 28 | *    contrÃŽler, a Frame buffer) are located in cluster_io. | 
|---|
| 29 | *    For those externals peripherals, hardware interrupts (HWI) are translated | 
|---|
| 30 | *    to software interrupts (WTI) by and IOPIC component, that is programmed | 
|---|
| 31 | *    to route all SWI to to processor 0 in cluster (0,0). | 
|---|
| 32 | * | 
|---|
| 33 | * The boot sequence is the following: | 
|---|
| 34 | *   - Each processor initializes the stack pointer ($29) depending on proc_id. | 
|---|
| 35 | *   - Each processor initializes the CP0 EBASE register | 
|---|
| 36 | *   - Only processor 0 initializes the Interrupt vector. | 
|---|
| 37 | *       - Only processor 0 initializes the IOPIC component. | 
|---|
| 38 | *   - Each processor initializes its private XCU mask. | 
|---|
| 39 | *   - Each processor initializes the Status Register (SR) | 
|---|
| 40 | *   - Each processor jumps to the same main address in kernel mode... | 
|---|
| 41 | ********************************************************************************/ | 
|---|
| 42 |  | 
|---|
| 43 | #include "hard_config.h" | 
|---|
| 44 | #include "mips32_registers.h" | 
|---|
| 45 |  | 
|---|
| 46 | .section .reset,"ax",@progbits | 
|---|
| 47 |  | 
|---|
| 48 | .extern seg_stack_base | 
|---|
| 49 | .extern seg_xcu_base | 
|---|
| 50 | .extern seg_pic_base | 
|---|
| 51 | .extern seg_kcode_base | 
|---|
| 52 | .extern _interrupt_vector | 
|---|
| 53 | .extern _ioc_isr | 
|---|
| 54 | .extern _mmc_isr | 
|---|
| 55 | .extern _tty_isr | 
|---|
| 56 | .extern main | 
|---|
| 57 |  | 
|---|
| 58 | .globl  reset | 
|---|
| 59 | .ent    reset | 
|---|
| 60 | .align  2 | 
|---|
| 61 |  | 
|---|
| 62 | reset: | 
|---|
| 63 | .set noreorder | 
|---|
| 64 |  | 
|---|
| 65 | /* each proc computes  proc_id, lpid, cluster_xy */ | 
|---|
| 66 | mfc0    $26,    CP0_PROCID | 
|---|
| 67 | andi    $26,    $26,    0x3FF       /* at most 1024 processors */ | 
|---|
| 68 | move    $10,    $26                 /* $10 <= proc_id  */ | 
|---|
| 69 | li      $27,    NB_PROCS_MAX | 
|---|
| 70 | divu    $26,    $27 | 
|---|
| 71 | mfhi    $11                         /* $11 <= lpid */ | 
|---|
| 72 | mflo    $12                         /* $12 <= cluster_xy */ | 
|---|
| 73 |  | 
|---|
| 74 | /* each proc initializes stack pointer (64K per processor) */ | 
|---|
| 75 | srl     $8,     $12,    Y_WIDTH     /* $8  <= x */ | 
|---|
| 76 | li      $9,     Y_SIZE | 
|---|
| 77 | mul     $8,     $8,     $9          /* $8  <= x * Y_SIZE */ | 
|---|
| 78 | andi    $13,    $12,    (1<<Y_WIDTH)-1 | 
|---|
| 79 | addu    $8,     $8,     $13         /* $8  <= x * Y_SIZE + y */ | 
|---|
| 80 | mul     $8,     $8,     $27         /* $8  <= (x*Y_SIZE+y)*NB_PROCS_MAX */ | 
|---|
| 81 | addu    $10,    $11,    $8          /* $10 <= (x*Y_SIZE+y)*NB_PROCS_MAX + lpid */ | 
|---|
| 82 |  | 
|---|
| 83 | la      $27,    seg_stack_base | 
|---|
| 84 | addi    $26,    $10,    1           /* $26 <= (proc_id + 1)           */ | 
|---|
| 85 | sll     $26,    $26,    14          /* $26 <= (proc_id + 1) * 16K     */ | 
|---|
| 86 | addu    $29,    $27,    $26         /* $29 <= seg_stack_base(proc_id) */ | 
|---|
| 87 |  | 
|---|
| 88 | /* each proc initializes CP0 EBASE register */ | 
|---|
| 89 | la      $26,    seg_kcode_base | 
|---|
| 90 | mtc0    $26,    CP0_EBASE           /* CP0_EBASE <= seg_kcode_base */ | 
|---|
| 91 |  | 
|---|
| 92 | /* only proc (0,0,0) initializes interrupt vector for IOC, TTY, MMC     */ | 
|---|
| 93 | bne     $10,    $0,    reset_xcu | 
|---|
| 94 | nop | 
|---|
| 95 |  | 
|---|
| 96 | la      $26,    _interrupt_vector   /* interrupt vector address                */ | 
|---|
| 97 | la      $27,    _mmc_isr | 
|---|
| 98 | sw      $27,    32($26)             /* interrupt_vector[8] <= _mmc_isr         */ | 
|---|
| 99 | la      $27,    _ioc_isr | 
|---|
| 100 | sw      $27,    36($26)             /* interrupt_vector[9] <= _ioc_isr         */ | 
|---|
| 101 | la      $27,    _tty_isr | 
|---|
| 102 | sw      $27,    40($26)             /* interrupt_vector[10] <= _tty_isr        */ | 
|---|
| 103 |  | 
|---|
| 104 | /* only proc (0,0,0) initializes IOPIC : IOPIC_ADDRESS[i] <= &XICU[0].WTI_REG[i]   */ | 
|---|
| 105 |  | 
|---|
| 106 | #if USE_IOPIC | 
|---|
| 107 |  | 
|---|
| 108 | li      $20,    X_SIZE | 
|---|
| 109 | addi    $20,    $20,    -1 | 
|---|
| 110 | sll     $20,    $20,    4 | 
|---|
| 111 | li      $21,    Y_SIZE | 
|---|
| 112 | add     $22,    $20,    $21         /* $22 <= cluster(X_SIZE-1, Y_SIZE)        */ | 
|---|
| 113 |  | 
|---|
| 114 | mtc2    $22,    CP2_PADDR_EXT       /* CP2_PADDR_EXT <= cluster_io             */ | 
|---|
| 115 |  | 
|---|
| 116 | li      $24,    16                  /* $24  iteration (de)counter              */ | 
|---|
| 117 | la      $27,    seg_xcu_base        /* $27 <= &(XICU[0].WTI_REG[0])            */ | 
|---|
| 118 | la      $26,    seg_pic_base        /* $26 <= &IOPIC_ADDRESS[0]                */ | 
|---|
| 119 |  | 
|---|
| 120 | reset_loop: | 
|---|
| 121 | sw      $27,    0($26)              /* IOPIC_ADDRESS[i] <= &XICU[0].WTI_REG[i] */ | 
|---|
| 122 | addi    $24,    $24,    -1          /* decrement iteration index               */ | 
|---|
| 123 | addi    $27,    $27,     4          /* $27 <= &(XICU[0].WTI_REG[i++]           */ | 
|---|
| 124 | addi    $26,    $26,     16         /* $26 <= &IOPIC_ADDRESS[i++]              */ | 
|---|
| 125 | bne     $24,    $0, reset_loop | 
|---|
| 126 | nop | 
|---|
| 127 |  | 
|---|
| 128 | mtc2    $0,     CP2_PADDR_EXT       /* CP2_PADDR_EXT <= zero                   */ | 
|---|
| 129 |  | 
|---|
| 130 | #endif | 
|---|
| 131 |  | 
|---|
| 132 | reset_xcu: | 
|---|
| 133 |  | 
|---|
| 134 | /* only proc (x,y,0) receive IRQs and initialise HWI and WTI XICU masks */ | 
|---|
| 135 | bne     $11,    $0,     reset_end | 
|---|
| 136 | nop | 
|---|
| 137 | la      $26,    seg_xcu_base | 
|---|
| 138 | li      $27,    0b010010000000      /* offset for MSK_HWI_ENABLE[lpid == 0]    */ | 
|---|
| 139 | addu    $24,    $26,    $27         /* $24 <= &HWI_MASK                        */ | 
|---|
| 140 | li      $25,    0x0700                      /* TTY:HWI[10]  IOC:HWI[9]  MEMC:HWI[8]    */ | 
|---|
| 141 | sw      $25,    0($24)              /* set HWI mask                            */ | 
|---|
| 142 |  | 
|---|
| 143 | li      $27,    0b011010000000      /* offset for MSK_WTI_ENABLE[lpid == 0]    */ | 
|---|
| 144 | addu    $24,    $26,    $27         /* $24 <= $WTI_MASK                        */ | 
|---|
| 145 | li      $25,    0xFFFFFFFF          /* all WTI enabled                         */ | 
|---|
| 146 | sw      $25,    0($24)              /* set WTI mask                            */ | 
|---|
| 147 |  | 
|---|
| 148 | reset_end: | 
|---|
| 149 |  | 
|---|
| 150 | /* initializes SR register */ | 
|---|
| 151 | li      $26,    0x0000FF01 | 
|---|
| 152 | mtc0    $26,    $12                 /* SR <= kernel mode / IRQ enable */ | 
|---|
| 153 |  | 
|---|
| 154 | /* jumps to main in kernel mode */ | 
|---|
| 155 | la      $26,    main | 
|---|
| 156 | jr      $26 | 
|---|
| 157 | nop | 
|---|
| 158 |  | 
|---|
| 159 | .end    reset | 
|---|
| 160 |  | 
|---|
| 161 | .set reorder | 
|---|