~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to grub-core/boot/mips/loongson/fwstart.S

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-09-13 18:02:04 UTC
  • mfrom: (1.17.15 upstream)
  • mto: (17.6.27 experimental)
  • mto: This revision was merged to the branch mainline in revision 145.
  • Revision ID: package-import@ubuntu.com-20120913180204-mojnmocbimlom4im
Tags: upstream-2.00
ImportĀ upstreamĀ versionĀ 2.00

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010  Free Software Foundation, Inc.
 
4
 *
 
5
 *  GRUB is free software: you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation, either version 3 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  GRUB is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <grub/mips/loongson/serial.h>
 
20
#include <grub/mips/loongson/pci.h>
 
21
#include <grub/mips/loongson.h>
 
22
#include <grub/pci.h>
 
23
#include <grub/machine/serial.h>
 
24
#include <grub/machine/kernel.h>
 
25
#include <grub/ns8250.h>
 
26
#include <grub/cs5536.h>
 
27
#include <grub/smbus.h>
 
28
 
 
29
#ifndef FULOONG2F
 
30
#include <grub/vgaregs.h>
 
31
#define GRUB_SM712_REG_BASE 0x700000
 
32
#define GRUB_SM712_PCIID 0x0712126f
 
33
#endif
 
34
 
 
35
#ifdef FULOONG2F
 
36
#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2
 
37
#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200
 
38
#else
 
39
#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT0
 
40
#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200
 
41
#endif
 
42
 
 
43
        .set noreorder
 
44
        .set noat
 
45
        .set nomacro
 
46
        .set mips3
 
47
 
 
48
        .global start,_start,__start
 
49
start:
 
50
_start:
 
51
__start:        
 
52
        /* Put serial init as soon as possible.  But on Fuloong2f serial is past
 
53
           Geode, so on Fuloong2f we need Geode first.
 
54
        */
 
55
#ifndef FULOONG2F
 
56
        bal serial_hw_init
 
57
         nop
 
58
#endif
 
59
 
 
60
        /* Find CS5536 controller.  */
 
61
        /* $t4 chooses device in priority encoding.  */
 
62
        /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG.
 
63
           This way we don't need to sacrifice a register for it.  */
 
64
retry_cs5536:   
 
65
        /* We have only one bus (0). Function is 0.  */
 
66
        lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
 
67
        lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE)
 
68
        lui $t3, %hi(GRUB_CS5536_PCIID)
 
69
        addiu $t3, $t3, %lo(GRUB_CS5536_PCIID)
 
70
        ori $t4, $zero, 1
 
71
1:
 
72
        andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1)
 
73
        /* In case of failure try again. CS5536 may be slow to come up.  */
 
74
        beql  $t4, $zero, retry_cs5536
 
75
         nop
 
76
        sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
 
77
        lw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1)
 
78
        bnel  $t2, $t3, 1b
 
79
         sll $t4, $t4, 1
 
80
 
 
81
#ifndef FULOONG2F
 
82
        lui $a0, %hi(cs5536_found)
 
83
        bal message
 
84
         addiu $a0, $a0, %lo(cs5536_found)
 
85
        bal printhex
 
86
         move $a0, $t4
 
87
#endif
 
88
 
 
89
        lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
 
90
        li  $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED
 
91
        sw  $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0)
 
92
        
 
93
        /* Set GPIO LBAR.  */
 
94
        lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR)
 
95
        addiu $a0, $a0, %lo(GRUB_CS5536_MSR_GPIO_BAR)
 
96
        ori $a1, $zero, GRUB_CS5536_LBAR_GPIO
 
97
        /* Set mask to 0xf and enabled bit to 1.  */
 
98
        bal wrmsr
 
99
         ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
 
100
                          | GRUB_CS5536_LBAR_ENABLE) >> 32)
 
101
 
 
102
        bal gpio_init
 
103
         nop
 
104
 
 
105
#ifdef FULOONG2F
 
106
        bal serial_hw_init
 
107
         nop
 
108
#endif
 
109
 
 
110
        /* Initialise SMBus controller.  */
 
111
        /* Set SMBUS LBAR.  */
 
112
        lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR)
 
113
        addiu $a0, $a0, %lo(GRUB_CS5536_MSR_SMB_BAR)
 
114
        ori $a1, $zero, GRUB_CS5536_LBAR_SMBUS
 
115
        /* Set mask to 0xf and enabled bit to 1.  */
 
116
        bal wrmsr
 
117
         ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
 
118
                           | GRUB_CS5536_LBAR_ENABLE) >> 32)
 
119
 
 
120
        lui $a0, %hi(smbus_enabled)
 
121
        bal message
 
122
          addiu $a0, $a0, %lo(smbus_enabled)
 
123
 
 
124
        lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS)
 
125
 
 
126
        /* Disable SMB.  */
 
127
        sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
 
128
 
 
129
        /* Disable interrupts.  */
 
130
        sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0)
 
131
 
 
132
        /* Set as master.  */
 
133
        sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0)
 
134
 
 
135
        /* Launch SMBus controller at slowest speed possible.  */
 
136
        ori $t1, $zero, 0xff
 
137
        sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0)
 
138
        sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
 
139
 
 
140
        /* Yeeloong and Fuloong2f have only one memory slot.  */
 
141
        /* Output first byte on serial for debugging.  */
 
142
        ori $a1, $zero, GRUB_SMB_RAM_START_ADDR
 
143
        bal read_spd
 
144
         move $a0, $zero
 
145
        bal printhex
 
146
         move $a0, $v0
 
147
 
 
148
        bal read_spd
 
149
         ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR
 
150
        ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2
 
151
        lui $a0, %hi(unimplemented_memory_type)
 
152
        bne $t0, $v0, fatal
 
153
         addiu $a0, $a0, %lo(unimplemented_memory_type)
 
154
 
 
155
        /* And here is our goal: DDR2 controller initialisation.  */
 
156
        lui     $t0, %hi(GRUB_CPU_LOONGSON_CORECFG)
 
157
        ld      $t1, %lo(GRUB_CPU_LOONGSON_CORECFG) ($t0)
 
158
        /* Use addiu for sign-extension.  */
 
159
        addiu   $t2, $zero, ~(GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE|GRUB_CPU_LOONGSON_CORECFG_BUFFER_CPU)
 
160
        and     $t1, $t1, $t2
 
161
        sd      $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
 
162
 
 
163
        b continue
 
164
 
 
165
        . = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
 
166
tlb_refill:     
 
167
        mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
 
168
        mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
 
169
        move $s3, $ra
 
170
        lui $a0, %hi(epc)
 
171
        bal message
 
172
         addiu $a0, $a0, %lo(epc)
 
173
 
 
174
        bal printhex
 
175
         move $a0, $s1
 
176
 
 
177
        lui $a0, %hi(badvaddr)
 
178
        bal message
 
179
         addiu $a0, $a0, %lo(badvaddr)
 
180
 
 
181
        bal printhex
 
182
         move $a0, $s2
 
183
 
 
184
        lui $a0, %hi(return_msg)
 
185
        bal message
 
186
         addiu $a0, $a0, %lo(return_msg)
 
187
 
 
188
        bal printhex
 
189
         move $a0, $s3
 
190
        
 
191
        lui $a0, %hi(newline)
 
192
        bal message
 
193
         addiu $a0, $a0, %lo(newline)
 
194
 
 
195
        lui $a0, %hi(unhandled_tlb_refill)
 
196
        b fatal
 
197
         addiu $a0, $a0, %lo(unhandled_tlb_refill)
 
198
 
 
199
        . = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
 
200
cache_error:
 
201
        lui $a0, %hi(unhandled_cache_error)
 
202
        b fatal
 
203
         addiu $a0, $a0, %lo(unhandled_cache_error)
 
204
 
 
205
        . = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
 
206
other_exception:
 
207
        mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE
 
208
        mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
 
209
        mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
 
210
        lui $a0, %hi(cause)
 
211
        bal message
 
212
         addiu $a0, $a0, %lo(cause)
 
213
 
 
214
        bal printhex
 
215
         move $a0, $s0
 
216
 
 
217
        lui $a0, %hi(epc)
 
218
        bal message
 
219
         addiu $a0, $a0, %lo(epc)
 
220
 
 
221
        bal printhex
 
222
         move $a0, $s1
 
223
 
 
224
        lui $a0, %hi(badvaddr)
 
225
        bal message
 
226
         addiu $a0, $a0, %lo(badvaddr)
 
227
 
 
228
        bal printhex
 
229
         move $a0, $s2
 
230
        
 
231
        lui $a0, %hi(newline)
 
232
        bal message
 
233
         addiu $a0, $a0, %lo(newline)
 
234
        
 
235
        lui $a0, %hi(unhandled_exception)
 
236
        b fatal
 
237
         addiu $a0, $a0, %lo(unhandled_exception)
 
238
 
 
239
gpio_init:
 
240
        lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
 
241
        addiu  $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
 
242
        lui $t1, %hi (gpio_dump)
 
243
        addiu $t1, $t1, %lo (gpio_dump)
 
244
 
 
245
1:      
 
246
        lw $t2, 0($t1)
 
247
        sw $t2, 0($t0)
 
248
        addiu $t0, $t0, 4
 
249
        addiu $t1, $t1, 4
 
250
        lui $t2, %hi (gpio_dump_end)
 
251
        addiu $t2, $t2, %lo (gpio_dump_end)
 
252
        bne $t1, $t2, 1b
 
253
         nop
 
254
        jr $ra
 
255
         nop
 
256
 
 
257
        /* Same as similarly named C function but in asm since
 
258
           we need it early.  */
 
259
        /* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2.  */
 
260
serial_hw_init:
 
261
        move $t2, $ra
 
262
#ifdef FULOONG2F
 
263
        lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO)
 
264
        addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO)
 
265
        lui $a1, %hi (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3    \
 
266
                     | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP         \
 
267
                     | GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86    \
 
268
                     | GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1)
 
269
        ori $a1, $a1, (GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 \
 
270
                       | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1)
 
271
        bal wrmsr
 
272
         move $a2, $zero
 
273
 
 
274
        lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
 
275
        addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
 
276
        li $a1, 2
 
277
        bal wrmsr
 
278
         move $a2, $zero
 
279
 
 
280
        lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
 
281
        addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
 
282
        li $a1, 2
 
283
        bal wrmsr
 
284
         move $a2, $zero
 
285
#endif
 
286
        
 
287
        lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
 
288
 
 
289
        /* Turn off the interrupt.  */
 
290
        sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_IER)($t0)
 
291
 
 
292
        /* Set DLAB.  */
 
293
        ori $t1, $zero, UART_DLAB
 
294
        sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
 
295
 
 
296
        /* Set the baud rate 115200.  */
 
297
        ori $t1, $zero, GRUB_MACHINE_SERIAL_DIVISOR_115200
 
298
        sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLL)($t0) 
 
299
        sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLH)($t0) 
 
300
 
 
301
        /* Set the line status.  */
 
302
        ori $t1, $zero, (UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT)
 
303
        sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
 
304
 
 
305
        /* Enable the FIFO.  */
 
306
        ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1
 
307
        sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_FCR)($t0)
 
308
 
 
309
        /* Turn on DTR and RTS.  */
 
310
        ori $t1, $zero, UART_ENABLE_DTRRTS
 
311
        sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_MCR)($t0)
 
312
 
 
313
        /* Let message return to original caller.  */
 
314
        lui  $a0, %hi(notification_string)
 
315
        addiu $a0, $a0, %lo(notification_string)
 
316
        move $ra, $t2
 
317
 
 
318
        /* Print message on serial console.  */
 
319
        /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0.  */
 
320
message:
 
321
        lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
 
322
1:
 
323
        lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
 
324
        andi $t1, $t1, UART_EMPTY_TRANSMITTER
 
325
        beq $t1, $zero, 1b
 
326
         nop
 
327
        lb  $t1, 0($a0)
 
328
        sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
 
329
        bne $t1, $zero, 1b
 
330
         addiu $a0, $a0, 1
 
331
        jr  $ra
 
332
         nop
 
333
        
 
334
        /* Print 32-bit hexadecimal on serial.
 
335
           In:  $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2
 
336
        */
 
337
printhex:
 
338
        lui $t0, %hi  (GRUB_MACHINE_SERIAL_PORT)
 
339
        ori $t2, $zero, 8
 
340
1:
 
341
        lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
 
342
        andi $t1, $t1, UART_EMPTY_TRANSMITTER
 
343
        beq $t1, $zero, 1b
 
344
         nop
 
345
        srl  $t1, $a0, 28
 
346
        addiu $t1, $t1, -10
 
347
        blt  $t1, $zero, 2f
 
348
         sll  $a0, $a0, 4
 
349
        addiu $t1, $t1, 'A'-10-'0' 
 
350
2:      addiu $t1, $t1, '0'+10
 
351
        sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
 
352
        addiu $t2, $t2, -1
 
353
        bne $t2, $zero, 1b
 
354
         nop
 
355
        jr  $ra
 
356
         nop
 
357
 
 
358
fatal:
 
359
        bal message
 
360
         nop
 
361
self:
 
362
        b self
 
363
         nop
 
364
        
 
365
        /* Write CS5536 MSR.
 
366
           In:   $a0 address, $a1 lower word, $a2 upper word.
 
367
           Out:  None
 
368
           Clobbered:    $t0
 
369
        */
 
370
wrmsr:
 
371
        lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
 
372
        sw  $a0, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_ADDR) ($t0)
 
373
        sw  $a1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA0) ($t0)
 
374
        jr $ra
 
375
         sw  $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0)
 
376
 
 
377
        /* Wait for SMBus data or empty transmitter.  */
 
378
        /* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1  */
 
379
smbus_wait:
 
380
1:      
 
381
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE)
 
382
        lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
383
        andi $t1, $t0, GRUB_CS5536_SMB_REG_STATUS_SDAST
 
384
        bne $t1, $zero, return
 
385
         nop
 
386
        andi $t1, $t0, (GRUB_CS5536_SMB_REG_STATUS_BER | GRUB_CS5536_SMB_REG_STATUS_NACK)
 
387
        beq $t1, $zero, 1b
 
388
         nop
 
389
        jr $a0
 
390
         nop
 
391
return:
 
392
        jr $ra
 
393
         nop
 
394
        
 
395
        /* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure).
 
396
           Clobbered: $t0, $t1, $t2, $t3, $a0. */
 
397
read_spd:
 
398
        move $t2, $a0
 
399
        move $t3, $ra
 
400
        lui $a0, %hi(read_spd_fail)
 
401
        addiu $a0, $a0, %hi(read_spd_fail)
 
402
 
 
403
        /* Send START.  */
 
404
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
 
405
        lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
406
        ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
 
407
        bal smbus_wait
 
408
         sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
409
        
 
410
        /* Send device address.  */
 
411
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
 
412
        sll $t1, $a1, 1
 
413
        bal smbus_wait
 
414
         sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
415
 
 
416
        /* Send ACK.  */
 
417
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
 
418
        lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
419
        ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_ACK
 
420
        sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
421
 
 
422
        /* Send byte address.  */
 
423
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
 
424
        bal smbus_wait
 
425
         sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
426
 
 
427
        /* Send START.  */
 
428
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
 
429
        lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
430
        ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
 
431
        bal smbus_wait
 
432
         sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
433
 
 
434
        /* Send device address.  */
 
435
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
 
436
        sll $t1, $a1, 1
 
437
        ori $t1, $t1, 1
 
438
        bal smbus_wait
 
439
         sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
440
 
 
441
        /* Send STOP.  */
 
442
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
 
443
        lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
444
        ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_STOP
 
445
        bal smbus_wait
 
446
         sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
447
 
 
448
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
 
449
        lb $v0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
450
        jr $t3
 
451
         andi $v0, $v0, 0xff
 
452
read_spd_fail:
 
453
        jr $t3
 
454
         ori $v0, $v0, 0x100
 
455
 
 
456
notification_string:    .asciz "GRUB "
 
457
cs5536_found:   .asciz "CS5536 at "
 
458
sm_failed: .asciz "SM transaction failed.\n\r"
 
459
unhandled_tlb_refill:   .asciz "Unhandled TLB refill.\n\r"
 
460
unhandled_cache_error:  .asciz "Unhandled cache error.\n\r"
 
461
unhandled_exception:    .asciz "Unhandled exception.\n\r"
 
462
smbus_enabled:  .asciz "SMBus controller enabled.\n\r"
 
463
unimplemented_memory_type:      .asciz "non-DDR2 memory isn't supported.\n\r"
 
464
no_cas_latency:         .asciz "Couldn't determine CAS latency.\n\r"
 
465
cause:   .asciz "Cause: "
 
466
epc:    .asciz "\n\rEPC: "
 
467
badvaddr:       .asciz "\n\rBadVaddr: "
 
468
newline:        .asciz "\n\r"
 
469
return_msg:       .asciz "\n\rReturn address: "
 
470
caches_enabled: .asciz "Caches enabled\n\r"
 
471
 
 
472
        .p2align 3
 
473
 
 
474
regdump:
 
475
        .quad 0x0100010000000101 /* 0 */
 
476
        .quad 0x0100010100000000 /* 2 */
 
477
        .quad 0x0101000001000000 /* 3 */
 
478
        .quad 0x0100020200010101 /* 4 */
 
479
        .quad 0x0a04030603050203 /* 6 */
 
480
        .quad 0x0f0e040000010a0b /* 7 */
 
481
#ifdef FULOONG2F
 
482
        .quad 0x0000000100000001 /* 8 */
 
483
#else
 
484
        .quad 0x0000010200000102 /* 8 */
 
485
#endif
 
486
        .quad 0x0000060c00000000 /* 9 */
 
487
        .quad 0x2323233f3f1f0200 /* a */
 
488
        .quad 0x5f7f232323232323 /* b */
 
489
        .quad 0x002a3c0615000000 /* c */
 
490
        .quad 0x002a002a002a002a /* d */
 
491
        .quad 0x002a002a002a002a /* e */
 
492
#ifdef FULOONG2F
 
493
        .quad 0x00b40020005b0004 /* f */
 
494
#else
 
495
        .quad 0x00b40020006d0004 /* f */
 
496
#endif
 
497
        .quad 0x070007ff00000087 /* 10 */
 
498
        .quad 0x000000000016101f /* 11 */
 
499
        .quad 0x001c000000000000 /* 12 */
 
500
        .quad 0x28e1000200c8006b /* 13 */
 
501
        .quad 0x0000204200c8002f /* 14 */
 
502
        .quad 0x0000000000030d40 /* 15 */
 
503
        .quad 0 /* 16 */
 
504
        .quad 0 /* 17 */
 
505
        .quad 0 /* 18 */
 
506
        .quad 0 /* 19 */
 
507
        .quad 0 /* 1a */
 
508
        .quad 0 /* 1b */
 
509
        .quad 0 /* 1c */
 
510
 
 
511
/* Dump of GPIO connections. FIXME: Remove useless and macroify.  */
 
512
gpio_dump:
 
513
#ifdef FULOONG2F
 
514
        .long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000
 
515
        .long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000
 
516
        .long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000
 
517
        .long 0x7df3820c, 0x3df3c20c, 0xffff0000, 0x00000000
 
518
        .long 0xffff0000, 0xffff0000, 0x3de3c21c, 0x3d83c27c
 
519
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
520
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
521
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
522
        .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
 
523
        .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
 
524
        .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
 
525
        .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
 
526
        .long 0xffff0000, 0xffff0000, 0xefff1000, 0xefff1000
 
527
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
528
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
529
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
530
#else
 
531
        .long 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000
 
532
        .long 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000
 
533
        .long 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000
 
534
        .long 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000
 
535
        .long 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064
 
536
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
537
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
538
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
539
        .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
 
540
        .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
 
541
        .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
 
542
        .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
 
543
        .long 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000
 
544
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
545
        .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
 
546
        .long 0x00000000, 0x50000000, 0x00000000, 0x00000000
 
547
#endif
 
548
gpio_dump_end:  
 
549
 
 
550
        .p2align
 
551
 
 
552
write_dumpreg:  
 
553
        ld $t2, 0($t6)
 
554
        sd $t2, 0($t4)
 
555
        addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
 
556
        jr $ra
 
557
         addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
 
558
 
 
559
continue:
 
560
        lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
 
561
        addiu $t4, $t4, %lo(GRUB_CPU_LOONGSON_DDR2_BASE)
 
562
        lui $t6, %hi(regdump)
 
563
 
 
564
        /* 0 */
 
565
        bal write_dumpreg
 
566
         addiu $t6, $t6, %lo(regdump)
 
567
 
 
568
        /* 1 */
 
569
        ori $a1, $a1, GRUB_SMB_RAM_START_ADDR
 
570
        move $t8, $zero
 
571
        lui  $t5, 0x0001
 
572
        bal read_spd
 
573
         ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR
 
574
        ori $t7, $zero, 8
 
575
        bne $v0, $t7, 1f
 
576
         ori $t5, $t5, 0x0001
 
577
        ori $t8, $t8, GRUB_CPU_LOONGSON_DDR2_REG1_HI_8BANKS
 
578
1:
 
579
        dsll $t8, $t8, 32
 
580
        or $t5, $t5, $t8
 
581
        sd  $t5, 0 ($t4)
 
582
        addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
 
583
 
 
584
        /* 2 */
 
585
        bal write_dumpreg
 
586
         nop
 
587
 
 
588
        /* 3 */
 
589
        bal write_dumpreg
 
590
         nop
 
591
 
 
592
        /* 4 */
 
593
        bal write_dumpreg
 
594
         nop
 
595
 
 
596
        /* 5 */
 
597
        /* FIXME: figure termination resistance.  */
 
598
        ori $t5, $zero, 0x2
 
599
        bal read_spd
 
600
         ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR
 
601
        /* $v0 = 15 - $v0.  */
 
602
        xori $v0, $v0, 0xf
 
603
        andi $v0, $v0, 0x7
 
604
        sll $v0, $v0, 8
 
605
        or $t5, $t5, $v0
 
606
 
 
607
        /* Find the fastest supported CAS latency.  */
 
608
        bal read_spd
 
609
         ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR
 
610
        ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE
 
611
        ori $t1, $zero, (1 << GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE)
 
612
2:      
 
613
        and $t2, $t1, $v0
 
614
        bne $t2, $zero, 1f
 
615
         ori $t3, $zero, 8
 
616
        lui $a0, %hi(no_cas_latency)
 
617
        beq $t0, $t3, fatal
 
618
         addiu $a0, $a0, %lo(no_cas_latency)
 
619
        addiu $t0, $t0, 1
 
620
        b 2b
 
621
         sll $t1, $t1, 1
 
622
1:
 
623
        sll $t0, $t0, 16
 
624
        or $t5, $t5, $t0
 
625
        
 
626
        bal read_spd
 
627
         ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR
 
628
        /* $v0 = 15 - ($v0 + 1) = 14 - $v0.  */
 
629
        addiu $v0, $v0, 1
 
630
        xori $v0, $v0, 0xf
 
631
        andi $v0, $v0, 0x7
 
632
        sll $v0, 24
 
633
        or $t5, $t5, $v0
 
634
        sd  $t5, 0 ($t4)
 
635
 
 
636
        addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
 
637
        
 
638
        ori $t7, $zero, 0x16
 
639
 
 
640
1:      
 
641
        ld $t2, 0($t6)
 
642
        sd $t2, 0($t4)
 
643
        addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
 
644
        addiu $t7, $t7, -1
 
645
        bne $t7, $zero, 1b
 
646
         addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
 
647
        
 
648
        lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
 
649
        ld  $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
 
650
        ori $t0, $zero, 1
 
651
        dsll $t0, $t0, 40
 
652
        or $t5, $t5, $t0
 
653
        sd  $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
 
654
 
 
655
        /* Desactivate DDR2 registers.  */
 
656
        lui     $t0, %hi (GRUB_CPU_LOONGSON_CORECFG)
 
657
        ld      $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
 
658
        ori     $t1, $t1, GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE
 
659
        sd      $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
 
660
 
 
661
        /* Enable cache.  */
 
662
        mfc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
 
663
        addiu   $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
 
664
        and     $t0, $t1, $t1
 
665
        /* Set line size to 32 bytes and disabled cache.  */
 
666
        ori     $t0, $t0, (GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE \
 
667
                           | GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE \
 
668
                           | GRUB_CPU_LOONGSON_CACHE_ACCELERATED)
 
669
        mtc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
 
670
 
 
671
        /* Invalidate all I-cache entries.  */
 
672
        srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_ISIZE_SHIFT
 
673
        andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
 
674
        ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
 
675
                               - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
 
676
                               - GRUB_CPU_LOONGSON_I_CACHE_LOG_WAYS))
 
677
        sll $t1, $t2, $t1
 
678
        lui $t2, 0x8000
 
679
 
 
680
1:      
 
681
        cache GRUB_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE, 0($t2)
 
682
        addiu $t1, $t1, -1
 
683
        bne $t1, $zero, 1b
 
684
         addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET)
 
685
 
 
686
        /* Invalidate all D-cache entries.  */
 
687
        srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT
 
688
        andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
 
689
        ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
 
690
                               - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
 
691
                               - GRUB_CPU_LOONGSON_D_CACHE_LOG_WAYS))
 
692
        sll $t1, $t2, $t1
 
693
        lui $t2, 0x8000
 
694
        mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
 
695
        mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
 
696
1:
 
697
        /* All four ways.  */
 
698
        cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 0($t2)
 
699
        cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 1($t2)
 
700
        cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 2($t2)
 
701
        cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 3($t2)
 
702
        addiu $t1, $t1, -1
 
703
        bne $t1, $zero, 1b
 
704
         addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
 
705
 
 
706
        /* Invalidate all S-cache entries.  */
 
707
        ori $t1, $zero, (1 << (GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE \
 
708
                               - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
 
709
                               - GRUB_CPU_LOONGSON_S_CACHE_LOG_WAYS))
 
710
        lui $t2, 0x8000
 
711
        mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
 
712
        mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
 
713
1:
 
714
        /* All four ways.  */
 
715
        cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 0($t2)
 
716
        cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 1($t2)
 
717
        cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 2($t2)
 
718
        cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 3($t2)
 
719
        addiu $t1, $t1, -1
 
720
        bne $t1, $zero, 1b
 
721
         addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
 
722
        
 
723
        /* Finally enable cache.  */
 
724
        mfc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
 
725
        addiu   $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
 
726
        and     $t0, $t1, $t1
 
727
        ori     $t0, $t0, GRUB_CPU_LOONGSON_CACHE_CACHED
 
728
        mtc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
 
729
 
 
730
        lui $a0, %hi(caches_enabled)
 
731
        bal message
 
732
          addiu $a0, $a0, %lo(caches_enabled)
 
733
 
 
734
        /* Set ROM delay cycles to 1.  */
 
735
        lui $t0, %hi(GRUB_CPU_LOONGSON_LIOCFG)
 
736
        lw  $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
 
737
        addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_ROM_DELAY_MASK \
 
738
                            << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
 
739
        and $t1, $t1, $t2
 
740
        ori $t1, $t1, (1 << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
 
741
        sw  $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
 
742
        
 
743
        addiu $a0, $zero, -1
 
744
        addiu $a1, $zero, -1
 
745
 
 
746
        /* Take advantage of cache.  */
 
747
        lui $t0, %hi(cached_continue - 0x20000000)
 
748
        addiu $t0, $t0, %lo(cached_continue - 0x20000000)
 
749
        jr $t0
 
750
#ifdef FULOONG2F
 
751
         addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG2F)
 
752
#else
 
753
         addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG)
 
754
#endif
 
755
 
 
756
cached_continue:
 
757
#ifndef FULOONG2F
 
758
        /* We have to init video early enough or watchdog will reboot us.  */
 
759
 
 
760
        /* Setup PCI controller.  */
 
761
 
 
762
        lui    $t0, %hi (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO)
 
763
        lui    $t1, %hi(0x8000000c)
 
764
        addiu  $t1, $t1, %lo(0x8000000c)
 
765
 
 
766
        sw  $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) ($t0)
 
767
        li  $t1, 0xffffffff
 
768
        sw  $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) ($t0)
 
769
 
 
770
        li  $t0, GRUB_MACHINE_PCI_CONTROLLER_HEADER
 
771
        li  $t1, (GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER \
 
772
                  | GRUB_PCI_COMMAND_MEM_ENABLED)
 
773
        sh  $t0, GRUB_PCI_REG_COMMAND ($t1)
 
774
        li  $t1, ((1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) \
 
775
                  | GRUB_PCI_STATUS_FAST_B2B_CAPABLE         \
 
776
                  | GRUB_PCI_STATUS_66MHZ_CAPABLE            \
 
777
                  | GRUB_PCI_STATUS_CAPABILITIES)
 
778
        sh  $t0, GRUB_PCI_REG_STATUS ($t1)
 
779
        li  $t0, 0xff
 
780
        sw  $t0, GRUB_PCI_REG_CACHELINE ($t1)
 
781
        lui  $t1, %hi(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \
 
782
                      | GRUB_PCI_ADDR_MEM_PREFETCH)
 
783
        addiu  $t1, $t1,  %lo(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \
 
784
                              | GRUB_PCI_ADDR_MEM_PREFETCH)
 
785
        sw  $t0, GRUB_PCI_REG_ADDRESS_REG0 ($t1)
 
786
        sw  $zero, GRUB_PCI_REG_ADDRESS_REG1 ($t1)
 
787
 
 
788
        /* Find video.  */
 
789
        /* $t4 chooses device in priority encoding.  */
 
790
        /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG.
 
791
           This way we don't need to sacrifice a register for it.  */
 
792
retry_sm712:
 
793
        /* We have only one bus (0). Function is 0.  */
 
794
        lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
 
795
        lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE)
 
796
        lui $t3, %hi(GRUB_SM712_PCIID)
 
797
        addiu $t3, $t3, %lo(GRUB_SM712_PCIID)
 
798
        ori $t4, $zero, 1
 
799
1:
 
800
        andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1)
 
801
        /* In case of failure try again. SM712 may be slow to come up.  */
 
802
        beql  $t4, $zero, retry_sm712
 
803
         nop
 
804
        sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
 
805
        lw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1)
 
806
        bnel  $t2, $t3, 1b
 
807
         sll $t4, $t4, 1
 
808
 
 
809
        /* FIXME: choose address dynamically if needed.   */
 
810
#define SM712_MAP 0x04000000
 
811
        
 
812
        lui  $t2, %hi(SM712_MAP)
 
813
        sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
 
814
        sw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_ADDRESS_REG0) ($t1)
 
815
 
 
816
        /* Set latency.  */
 
817
        li   $t2, 0x8
 
818
        sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
 
819
        sw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_CACHELINE) ($t1)
 
820
 
 
821
        /* Enable address spaces.  */
 
822
        li   $t2, 0x7
 
823
        sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
 
824
        sw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_COMMAND) ($t1)
 
825
 
 
826
        lui   $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)
 
827
        li   $t2, 0x18
 
828
        sb   $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)($t3)
 
829
 
 
830
        lui   $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)
 
831
        li   $t2, 0x11
 
832
        sb   $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)($t3)
 
833
 
 
834
        li   $t2, ((((SM712_MAP & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK) \
 
835
                     >> GRUB_MACHINE_PCI_WIN_SHIFT)                  \
 
836
                   & GRUB_MACHINE_PCI_WIN_MASK))
 
837
        lui   $t3, %hi(0xbfe00110)
 
838
        addiu   $t3, $t3, %lo(0xbfe00110)
 
839
        sw   $t2, 0 ($t3)
 
840
        li   $t2, (GRUB_MACHINE_PCI_WIN1_ADDR                        \
 
841
                   | (SM712_MAP & GRUB_MACHINE_PCI_WIN_OFFSET_MASK))
 
842
 
 
843
        lui   $t3, %hi(GRUB_SM712_REG_BASE)
 
844
        addiu $t3, $t3, %lo(GRUB_SM712_REG_BASE)
 
845
        addu  $t2, $t2, $t3
 
846
        lui   $t0, %hi(init_table - 0x20000000)
 
847
        addiu $t0, $t0, %lo(init_table - 0x20000000)
 
848
        lui   $t1, %hi(init_table_end - 0x20000000)
 
849
        addiu $t1, $t1, %lo(init_table_end - 0x20000000)
 
850
        li    $t5, 0x80
 
851
        addiu $t6, $t2, 0x3c0
 
852
 
 
853
table_cont:     
 
854
        lb    $t3, 0($t0)
 
855
        andi  $t5, $t3, 0x80
 
856
        andi  $t3, $t3, 0x7f
 
857
        addu  $t3, $t3, $t6
 
858
        lb    $t4, 1($t0)
 
859
 
 
860
        bne   $zero, $t5, 1f
 
861
         addiu $t0, $t0, 2
 
862
        b  2f
 
863
         sb    $t4, 0($t3)
 
864
1:      
 
865
        lb    $t4, 0($t3)
 
866
2:      
 
867
        bne   $t0, $t1, table_cont
 
868
         nop
 
869
 
 
870
        lui   $t3, %hi(0x40c000 - GRUB_SM712_REG_BASE)
 
871
        addiu $t3, $t3, %lo(0x40c000 - GRUB_SM712_REG_BASE)
 
872
        addu  $t1, $t2, $t3 
 
873
        sw    $zero, 0xc ($t1)
 
874
        sw    $zero, 0x40 ($t1)
 
875
        li    $t3, 0x20000
 
876
        sw    $t3, 0x0 ($t1)
 
877
        lui   $t3, %hi(0x1020100)
 
878
        addiu $t3, $t3, %lo(0x1020100)
 
879
        sw    $t3, 0x10 ($t1)
 
880
 
 
881
        li    $t4, 0x16
 
882
        sb    $t4, GRUB_VGA_IO_SR_INDEX($t2)
 
883
 
 
884
        lb    $t4, GRUB_VGA_IO_SR_DATA($t2)
 
885
 
 
886
        b init_end
 
887
          nop
 
888
init_table:     
 
889
#include "sm712_start.S"
 
890
init_table_end:
 
891
        .align 4
 
892
init_end:       
 
893
#endif