| [622] | 1 | /******************************************************************************** | 
|---|
| [743] | 2 | *   File : reset.S | 
|---|
 | 3 | *   Author : Alain Greiner | 
|---|
 | 4 | *   Date : 15/01/2014 | 
|---|
| [622] | 5 | ********************************************************************************* | 
|---|
 | 6 | * This is a boot code for a generic multi-clusters / multi-processors | 
|---|
| [744] | 7 | * TSAR architecture (up to 256 clusters / up to 4  processors per cluster). | 
|---|
| [622] | 8 | * The physical address is 40 bits, and the 8 MSB bits A[39:32] define the | 
|---|
 | 9 | * cluster index. | 
|---|
 | 10 | * | 
|---|
| [744] | 11 | * As we don't want to use the virtual memory, the physical address is | 
|---|
| [629] | 12 | * equal to  the virtual address (identity mapping) and all processors stacks | 
|---|
| [744] | 13 | * and code segments are allocated in the physical memory bank in cluster 0. | 
|---|
| [622] | 14 | * | 
|---|
| [629] | 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 | * | 
|---|
| [622] | 18 | * There is one XCU iand one MMC per cluster. | 
|---|
 | 19 | * | 
|---|
| [629] | 20 | * There is one IOPIC component in cluster_io. | 
|---|
 | 21 | * | 
|---|
 | 22 | * There is two sets of peripherals: | 
|---|
 | 23 | * | 
|---|
| [744] | 24 | * 1) A block device and a single channel TTY controller are available | 
|---|
| [629] | 25 | *    in cluster(0,0). | 
|---|
 | 26 | * | 
|---|
| [744] | 27 | * 2) Other peripherals (including another Blockdevice, a multi-channels TTY | 
|---|
| [629] | 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 | * | 
|---|
| [622] | 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 | 
|---|
| [743] | 36 | *   - Only processor 0 initializes the Interrupt vector. | 
|---|
| [629] | 37 | *       - Only processor 0 initializes the IOPIC component. | 
|---|
| [622] | 38 | *   - Each processor initializes its private XCU mask. | 
|---|
| [744] | 39 | *   - Each processor initializes the Status Register (SR) | 
|---|
| [743] | 40 | *   - Each processor jumps to the same main address in kernel mode... | 
|---|
| [622] | 41 | ********************************************************************************/ | 
|---|
 | 42 |  | 
|---|
 | 43 | #include "hard_config.h" | 
|---|
 | 44 | #include "mips32_registers.h" | 
|---|
 | 45 |  | 
|---|
| [743] | 46 |     .section .reset,"ax",@progbits | 
|---|
| [622] | 47 |  | 
|---|
| [743] | 48 |     .extern seg_stack_base | 
|---|
 | 49 |     .extern seg_xcu_base | 
|---|
| [629] | 50 |         .extern seg_pic_base | 
|---|
| [622] | 51 |     .extern seg_kcode_base | 
|---|
| [743] | 52 |     .extern _interrupt_vector | 
|---|
 | 53 |     .extern _ioc_isr | 
|---|
 | 54 |     .extern _mmc_isr | 
|---|
| [629] | 55 |     .extern _tty_isr | 
|---|
| [622] | 56 |     .extern main | 
|---|
 | 57 |  | 
|---|
| [744] | 58 |     .globl  reset | 
|---|
| [743] | 59 |     .ent    reset | 
|---|
 | 60 |     .align  2 | 
|---|
| [622] | 61 |  | 
|---|
 | 62 | reset: | 
|---|
| [743] | 63 |         .set noreorder | 
|---|
| [622] | 64 |  | 
|---|
 | 65 | /* each proc computes  proc_id, lpid, cluster_xy */ | 
|---|
 | 66 |     mfc0    $26,    CP0_PROCID | 
|---|
| [743] | 67 |     andi    $26,    $26,    0x3FF       /* at most 1024 processors */ | 
|---|
| [622] | 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) */ | 
|---|
| [743] | 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 |  | 
|---|
| [622] | 83 |     la      $27,    seg_stack_base | 
|---|
| [743] | 84 |     addi    $26,    $10,    1           /* $26 <= (proc_id + 1)           */ | 
|---|
| [629] | 85 |     sll     $26,    $26,    14          /* $26 <= (proc_id + 1) * 16K     */ | 
|---|
| [743] | 86 |     addu    $29,    $27,    $26         /* $29 <= seg_stack_base(proc_id) */ | 
|---|
| [622] | 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 |  | 
|---|
| [629] | 92 | /* only proc (0,0,0) initializes interrupt vector for IOC, TTY, MMC     */ | 
|---|
| [743] | 93 |     bne     $10,    $0,    reset_xcu | 
|---|
| [622] | 94 |     nop | 
|---|
 | 95 |  | 
|---|
| [629] | 96 |     la      $26,    _interrupt_vector   /* interrupt vector address                */ | 
|---|
| [744] | 97 |     la      $27,    _mmc_isr | 
|---|
| [629] | 98 |     sw      $27,    32($26)             /* interrupt_vector[8] <= _mmc_isr         */ | 
|---|
| [744] | 99 |     la      $27,    _ioc_isr | 
|---|
| [629] | 100 |     sw      $27,    36($26)             /* interrupt_vector[9] <= _ioc_isr         */ | 
|---|
| [744] | 101 |     la      $27,    _tty_isr | 
|---|
| [629] | 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 |  | 
|---|
| [743] | 106 | #if USE_IOPIC | 
|---|
| [633] | 107 |  | 
|---|
| [629] | 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                   */ | 
|---|
| [743] | 129 |  | 
|---|
 | 130 | #endif | 
|---|
| [744] | 131 |  | 
|---|
| [622] | 132 | reset_xcu: | 
|---|
 | 133 |  | 
|---|
| [629] | 134 | /* only proc (x,y,0) receive IRQs and initialise HWI and WTI XICU masks */ | 
|---|
| [622] | 135 |     bne     $11,    $0,     reset_end | 
|---|
 | 136 |     nop | 
|---|
 | 137 |     la      $26,    seg_xcu_base | 
|---|
| [629] | 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                            */ | 
|---|
| [622] | 142 |  | 
|---|
| [629] | 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 |  | 
|---|
| [622] | 148 | reset_end: | 
|---|
 | 149 |  | 
|---|
 | 150 | /* initializes SR register */ | 
|---|
| [744] | 151 |     li      $26,    0x0000FF01 | 
|---|
| [743] | 152 |     mtc0    $26,    $12                 /* SR <= kernel mode / IRQ enable */ | 
|---|
| [622] | 153 |  | 
|---|
 | 154 | /* jumps to main in kernel mode */ | 
|---|
| [743] | 155 |     la      $26,    main | 
|---|
| [622] | 156 |     jr      $26 | 
|---|
 | 157 |     nop | 
|---|
 | 158 |  | 
|---|
| [743] | 159 |     .end    reset | 
|---|
| [622] | 160 |  | 
|---|
 | 161 |     .set reorder | 
|---|