Initialize UART in bootrom
Unless the UART is properly initialized, the console won't display any message until a next stage intializes it (OpenSBI) and then we will start to see messages after uploading the next bootroms. Follows the OpenSBI initialization for the UART setting the baud rate to 115200 and assuming a clock of 50 MHz.
This commit is contained in:
parent
417a4d5c75
commit
806023778b
@ -12,6 +12,28 @@
|
||||
|
||||
#define DRAM_BASE 0x80000000
|
||||
#define UART_BASE 0x40001000
|
||||
#define UART_BAUDRATE 115200
|
||||
#define UART_CLOCK 50000000
|
||||
|
||||
#define UART_BDIV ((UART_CLOCK + 8 * UART_BAUDRATE) / (16 * UART_BAUDRATE))
|
||||
#define UART_SHIFT 2
|
||||
|
||||
#define UART_RBR_OFFSET (0<<UART_SHIFT) /* In: Recieve Buffer Register */
|
||||
#define UART_THR_OFFSET (0<<UART_SHIFT) /* Out: Transmitter Holding Register */
|
||||
#define UART_DLL_OFFSET (0<<UART_SHIFT) /* Out: Divisor Latch Low */
|
||||
#define UART_IER_OFFSET (1<<UART_SHIFT) /* I/O: Interrupt Enable Register */
|
||||
#define UART_DLM_OFFSET (1<<UART_SHIFT) /* Out: Divisor Latch High */
|
||||
#define UART_FCR_OFFSET (2<<UART_SHIFT) /* Out: FIFO Control Register */
|
||||
#define UART_IIR_OFFSET (2<<UART_SHIFT) /* I/O: Interrupt Identification Register */
|
||||
#define UART_LCR_OFFSET (3<<UART_SHIFT) /* Out: Line Control Register */
|
||||
#define UART_MCR_OFFSET (4<<UART_SHIFT) /* Out: Modem Control Register */
|
||||
#define UART_LSR_OFFSET (5<<UART_SHIFT) /* In: Line Status Register */
|
||||
#define UART_MSR_OFFSET (6<<UART_SHIFT) /* In: Modem Status Register */
|
||||
#define UART_SCR_OFFSET (7<<UART_SHIFT) /* I/O: Scratch Register */
|
||||
#define UART_MDR1_OFFSET (8<<UART_SHIFT) /* I/O: Mode Register */
|
||||
|
||||
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
|
||||
#define UART_LSR_DR 0x01 /* Receiver data ready */
|
||||
|
||||
.macro PUTC, ch
|
||||
li a0, \ch
|
||||
@ -21,6 +43,7 @@
|
||||
.section .text.start, "ax", @progbits
|
||||
.globl _start
|
||||
_start:
|
||||
jal uart_init // Initialize console
|
||||
jal print_hello // Print initial message on HART 0 only
|
||||
|
||||
la t0, _hang
|
||||
@ -61,15 +84,48 @@ _hang:
|
||||
.section .text, "ax", @progbits
|
||||
|
||||
putchar:
|
||||
// Wait a bit before writing to UART
|
||||
li t0, 100000 // Delay a bit
|
||||
1:
|
||||
addi t0, t0, -1 // Decrement
|
||||
bne t0, zero, 1b // Repeat if not zero
|
||||
/* Wait until ready to transmit */
|
||||
|
||||
la t0, UART_BASE // Load UART base address
|
||||
1:
|
||||
lb t1, UART_LSR_OFFSET(t0) // Read Line Status Register
|
||||
andi t1, t1, UART_LSR_THRE // Transmitter Holding Register Empty
|
||||
beqz t1, 1b // Repeat if zero (not empty)
|
||||
|
||||
/* Write the character now */
|
||||
sb a0, UART_THR_OFFSET(t0) // Transmit character
|
||||
ret
|
||||
|
||||
uart_init:
|
||||
/* Assume reg_shift = 2 and reg_width = 2 */
|
||||
|
||||
la t0, UART_BASE // Load UART base address
|
||||
|
||||
/* From OpenSBI v1.5 lib/utils/serial/uart8250.c */
|
||||
|
||||
la t1, 0x00 // Disable all interrupts
|
||||
sb t1, UART_IER_OFFSET(t0)
|
||||
la t1, 0x80 // Enable DLAB
|
||||
sb t1, UART_LCR_OFFSET(t0)
|
||||
|
||||
la t1, UART_BDIV & 0xff // Set divisor low byte
|
||||
sb t1, UART_DLL_OFFSET(t0)
|
||||
la t1, (UART_BDIV >> 8) & 0xff // Set divisor high byte
|
||||
sb t1, UART_DLM_OFFSET(t0)
|
||||
|
||||
la t1, 0x03 // 8 bits, no parity, one stop bit
|
||||
sb t1, UART_LCR_OFFSET(t0)
|
||||
la t1, 0x01 // Enable FIFO
|
||||
sb t1, UART_FCR_OFFSET(t0)
|
||||
la t1, 0x00 // No modem control DTR RTS
|
||||
sb t1, UART_MCR_OFFSET(t0)
|
||||
|
||||
/* TODO: Clear line status */
|
||||
/* TODO: Read receive buffer */
|
||||
|
||||
la t1, 0x00 // Set scratchpad to 0
|
||||
sb t1, UART_SCR_OFFSET(t0)
|
||||
|
||||
// Write the character now
|
||||
la t0, UART_BASE // Transmitter Holding Buffer
|
||||
sb a0, 0(t0) // Write a0 byte
|
||||
ret
|
||||
|
||||
print_hello:
|
||||
|
Loading…
Reference in New Issue
Block a user