2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
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.
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.
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/>.
19
#include <grub/mips/loongson/serial.h>
20
#include <grub/mips/loongson/pci.h>
21
#include <grub/mips/loongson.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>
30
#include <grub/vgaregs.h>
31
#define GRUB_SM712_REG_BASE 0x700000
32
#define GRUB_SM712_PCIID 0x0712126f
36
#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2
37
#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200
39
#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT0
40
#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200
48
.global start,_start,__start
52
/* Put serial init as soon as possible. But on Fuloong2f serial is past
53
Geode, so on Fuloong2f we need Geode first.
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. */
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)
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
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)
82
lui $a0, %hi(cs5536_found)
84
addiu $a0, $a0, %lo(cs5536_found)
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)
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. */
99
ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
100
| GRUB_CS5536_LBAR_ENABLE) >> 32)
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. */
117
ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
118
| GRUB_CS5536_LBAR_ENABLE) >> 32)
120
lui $a0, %hi(smbus_enabled)
122
addiu $a0, $a0, %lo(smbus_enabled)
124
lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS)
127
sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
129
/* Disable interrupts. */
130
sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0)
133
sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0)
135
/* Launch SMBus controller at slowest speed possible. */
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)
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
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)
153
addiu $a0, $a0, %lo(unimplemented_memory_type)
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)
161
sd $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
165
. = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
167
mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
168
mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
172
addiu $a0, $a0, %lo(epc)
177
lui $a0, %hi(badvaddr)
179
addiu $a0, $a0, %lo(badvaddr)
184
lui $a0, %hi(return_msg)
186
addiu $a0, $a0, %lo(return_msg)
191
lui $a0, %hi(newline)
193
addiu $a0, $a0, %lo(newline)
195
lui $a0, %hi(unhandled_tlb_refill)
197
addiu $a0, $a0, %lo(unhandled_tlb_refill)
199
. = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
201
lui $a0, %hi(unhandled_cache_error)
203
addiu $a0, $a0, %lo(unhandled_cache_error)
205
. = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
207
mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE
208
mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
209
mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
212
addiu $a0, $a0, %lo(cause)
219
addiu $a0, $a0, %lo(epc)
224
lui $a0, %hi(badvaddr)
226
addiu $a0, $a0, %lo(badvaddr)
231
lui $a0, %hi(newline)
233
addiu $a0, $a0, %lo(newline)
235
lui $a0, %hi(unhandled_exception)
237
addiu $a0, $a0, %lo(unhandled_exception)
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)
250
lui $t2, %hi (gpio_dump_end)
251
addiu $t2, $t2, %lo (gpio_dump_end)
257
/* Same as similarly named C function but in asm since
259
/* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2. */
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)
274
lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
275
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
280
lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
281
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
287
lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
289
/* Turn off the interrupt. */
290
sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_IER)($t0)
293
ori $t1, $zero, UART_DLAB
294
sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
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)
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)
305
/* Enable the FIFO. */
306
ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1
307
sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_FCR)($t0)
309
/* Turn on DTR and RTS. */
310
ori $t1, $zero, UART_ENABLE_DTRRTS
311
sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_MCR)($t0)
313
/* Let message return to original caller. */
314
lui $a0, %hi(notification_string)
315
addiu $a0, $a0, %lo(notification_string)
318
/* Print message on serial console. */
319
/* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */
321
lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
323
lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
324
andi $t1, $t1, UART_EMPTY_TRANSMITTER
328
sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
334
/* Print 32-bit hexadecimal on serial.
335
In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2
338
lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
341
lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
342
andi $t1, $t1, UART_EMPTY_TRANSMITTER
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)
366
In: $a0 address, $a1 lower word, $a2 upper word.
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)
375
sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0)
377
/* Wait for SMBus data or empty transmitter. */
378
/* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1 */
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
386
andi $t1, $t0, (GRUB_CS5536_SMB_REG_STATUS_BER | GRUB_CS5536_SMB_REG_STATUS_NACK)
395
/* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure).
396
Clobbered: $t0, $t1, $t2, $t3, $a0. */
400
lui $a0, %hi(read_spd_fail)
401
addiu $a0, $a0, %hi(read_spd_fail)
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
408
sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
410
/* Send device address. */
411
lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
414
sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
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)
422
/* Send byte address. */
423
lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
425
sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
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
432
sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
434
/* Send device address. */
435
lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
439
sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
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
446
sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
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)
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"
475
.quad 0x0100010000000101 /* 0 */
476
.quad 0x0100010100000000 /* 2 */
477
.quad 0x0101000001000000 /* 3 */
478
.quad 0x0100020200010101 /* 4 */
479
.quad 0x0a04030603050203 /* 6 */
480
.quad 0x0f0e040000010a0b /* 7 */
482
.quad 0x0000000100000001 /* 8 */
484
.quad 0x0000010200000102 /* 8 */
486
.quad 0x0000060c00000000 /* 9 */
487
.quad 0x2323233f3f1f0200 /* a */
488
.quad 0x5f7f232323232323 /* b */
489
.quad 0x002a3c0615000000 /* c */
490
.quad 0x002a002a002a002a /* d */
491
.quad 0x002a002a002a002a /* e */
493
.quad 0x00b40020005b0004 /* f */
495
.quad 0x00b40020006d0004 /* f */
497
.quad 0x070007ff00000087 /* 10 */
498
.quad 0x000000000016101f /* 11 */
499
.quad 0x001c000000000000 /* 12 */
500
.quad 0x28e1000200c8006b /* 13 */
501
.quad 0x0000204200c8002f /* 14 */
502
.quad 0x0000000000030d40 /* 15 */
511
/* Dump of GPIO connections. FIXME: Remove useless and macroify. */
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
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
555
addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
557
addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
560
lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
561
addiu $t4, $t4, %lo(GRUB_CPU_LOONGSON_DDR2_BASE)
562
lui $t6, %hi(regdump)
566
addiu $t6, $t6, %lo(regdump)
569
ori $a1, $a1, GRUB_SMB_RAM_START_ADDR
573
ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR
577
ori $t8, $t8, GRUB_CPU_LOONGSON_DDR2_REG1_HI_8BANKS
582
addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
597
/* FIXME: figure termination resistance. */
600
ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR
601
/* $v0 = 15 - $v0. */
607
/* Find the fastest supported CAS latency. */
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)
616
lui $a0, %hi(no_cas_latency)
618
addiu $a0, $a0, %lo(no_cas_latency)
627
ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR
628
/* $v0 = 15 - ($v0 + 1) = 14 - $v0. */
636
addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
643
addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
646
addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
648
lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
649
ld $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
653
sd $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
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)
662
mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
663
addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
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
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))
681
cache GRUB_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE, 0($t2)
684
addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET)
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))
694
mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
695
mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
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)
704
addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
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))
711
mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
712
mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
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)
721
addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
723
/* Finally enable cache. */
724
mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
725
addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
727
ori $t0, $t0, GRUB_CPU_LOONGSON_CACHE_CACHED
728
mtc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
730
lui $a0, %hi(caches_enabled)
732
addiu $a0, $a0, %lo(caches_enabled)
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)
740
ori $t1, $t1, (1 << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
741
sw $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
746
/* Take advantage of cache. */
747
lui $t0, %hi(cached_continue - 0x20000000)
748
addiu $t0, $t0, %lo(cached_continue - 0x20000000)
751
addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG2F)
753
addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG)
758
/* We have to init video early enough or watchdog will reboot us. */
760
/* Setup PCI controller. */
762
lui $t0, %hi (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO)
763
lui $t1, %hi(0x8000000c)
764
addiu $t1, $t1, %lo(0x8000000c)
766
sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) ($t0)
768
sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) ($t0)
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)
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)
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. */
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)
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
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)
809
/* FIXME: choose address dynamically if needed. */
810
#define SM712_MAP 0x04000000
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)
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)
821
/* Enable address spaces. */
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)
826
lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)
828
sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)($t3)
830
lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)
832
sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)($t3)
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)
840
li $t2, (GRUB_MACHINE_PCI_WIN1_ADDR \
841
| (SM712_MAP & GRUB_MACHINE_PCI_WIN_OFFSET_MASK))
843
lui $t3, %hi(GRUB_SM712_REG_BASE)
844
addiu $t3, $t3, %lo(GRUB_SM712_REG_BASE)
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)
851
addiu $t6, $t2, 0x3c0
867
bne $t0, $t1, table_cont
870
lui $t3, %hi(0x40c000 - GRUB_SM712_REG_BASE)
871
addiu $t3, $t3, %lo(0x40c000 - GRUB_SM712_REG_BASE)
877
lui $t3, %hi(0x1020100)
878
addiu $t3, $t3, %lo(0x1020100)
882
sb $t4, GRUB_VGA_IO_SR_INDEX($t2)
884
lb $t4, GRUB_VGA_IO_SR_DATA($t2)
889
#include "sm712_start.S"