Skip to content

Commit a1d8614

Browse files
committed
Switch from 16550a to Uartlite
1 parent efaaeff commit a1d8614

File tree

32 files changed

+475
-693
lines changed

32 files changed

+475
-693
lines changed

README.md

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,12 @@ The CPU is implemented using a variable-size build-order-independent subframe ar
2525
| `0x00000000` | Configurable | R/X | Program ROM |
2626
| Configurable | Configurable | R/X | Data ROM |
2727
| `0x80000000` | Configurable | R/W/X/A\* | RAM |
28-
| `0xf0000000` | `0x4` | R/W | `mtime` |
29-
| `0xf0000004` | `0x4` | R/W | `mtimeh` |
30-
| `0xf0000008` | `0x4` | R/W | `mtimecmp` |
31-
| `0xf000000c` | `0x4` | R/W | `mtimecmph` |
32-
| `0xf0000010` | `0x20` | R/W | UART0 |
33-
| `0xf0000030` | `0x20` | R/W | UART1 |
34-
| `0xf0000050` | `0x20` | R/W | UART2 |
35-
| `0xf0000070` | `0x20` | R/W | UART3 |
28+
| `0xf0000000` | `0x8` | R/W | `mtime` |
29+
| `0xf0000008` | `0x8` | R/W | `mtimecmp` |
30+
| `0xf0000010` | `0x10` | R/W | UART0 |
31+
| `0xf0000020` | `0x10` | R/W | UART1 |
32+
| `0xf0000030` | `0x10` | R/W | UART2 |
33+
| `0xf0000040` | `0x10` | R/W | UART3 |
3634
| `0xfffffff0` | `0x4` | R/W | Syscon |
3735

3836
\* Atomic instructions are only supported in RAM.
@@ -49,27 +47,19 @@ The `mtime` and `mtimecmp` registers are mapped to `0xf0000000` and `0xf0000008`
4947

5048
### UART
5149

52-
The processor includes four identical emulated UART 16550 peripherals based on [this datasheet](https://caro.su/msx/ocm_de1/16550.pdf). The UARTs support the following features:
50+
The processor includes four instances of an emulated UART peripheral compatible with the [AXI UART Lite](https://docs.amd.com/v/u/en-US/pg142-axi-uartlite). The UARTs support the following features:
5351

52+
- Up to 32 data bits.
5453
- Configurable FIFO capacity (up to 253 bytes) for TX and RX, stored as a variable in the CONFIG processor.
5554
- Theoretical maximum transfer rate of 121440 bits/sec (253 bytes/tick).
56-
- Line Status Register flags: Transmitter Empty, THR Empty, Overrun Error, Data Ready.
57-
- FIFO Control Register flags: Enable FIFOs (0 is ignored), Reset RX/TX FIFO
58-
59-
The UART registers have a stride of 4 bytes to simplify some internal logic.
60-
61-
| Offset | Access Type | Register |
62-
| ------ | ----------- | ---------------------------- |
63-
| `0x00` | R | Receiver Holding Register |
64-
| `0x00` | W | Transmitter Holding Register |
65-
| `0x04` | R/W | Interrupt Enable Register |
66-
| `0x08` | R | Interrupt Status Register |
67-
| `0x08` | W | FIFO Control Register |
68-
| `0x0c` | R/W | Line Control Register |
69-
| `0x10` | R/W | Modem Control Register |
70-
| `0x14` | R | Line Status Register |
71-
| `0x18` | R | Modem Status Register |
72-
| `0x1c` | R/W | Scratch Pad Register |
55+
- Edge-triggered interrupts for RX FIFO non-empty and TX FIFO empty.
56+
57+
| Offset | Access Type | Register |
58+
| ------ | ----------- | -------- |
59+
| `0x0` | R | RX FIFO |
60+
| `0x4` | W | TX FIFO |
61+
| `0x8` | R | Status |
62+
| `0xc` | W | Control |
7363

7464
Each UART is implemented as two circular buffers in a memory bank with the following layout. Note that RX refers to data sent to / read by the processor, and TX refers to data sent from / written by the processor.
7565

@@ -82,28 +72,19 @@ Each UART is implemented as two circular buffers in a memory bank with the follo
8272
| 510 | TX buffer read pointer |
8373
| 511 | TX buffer write pointer |
8474

85-
Read/write pointers are stored modulo `capacity + 1`. A buffer is empty when `rptr == wptr` and full when `rptr == (wptr + 1) % (capacity + 1)`. If the RX buffer is full and more data arrives, producers should discard the new data rather than overwriting old data in the buffer. An overflow may optionally be indicated to the processor by setting bit 8 of `rx_wptr` (ie. `rx_wptr | 0x100`).
75+
Read/write pointers are stored modulo `capacity + 1`. A buffer is empty when `rptr == wptr` and full when `rptr == (wptr + 1) % (capacity + 1)`. If the RX buffer is full and more data arrives, producers should discard the new data rather than overwriting old data in the buffer.
8676

87-
Note that the processor itself does not set the TX overflow flag or prevent code from overflowing the TX buffer. Users are expected to check the Line Status Register and avoid writing too much data at once.
77+
Note that the processor itself does not prevent code from overflowing the TX buffer. Users are expected to check the Status register and avoid writing too much data at once.
8878

89-
If any UART interrupt is pending, `mip.MEIP` will become pending. To make UART interrupts visible to S-mode, M-mode software must either delegate `mip.MEIP` via `mideleg`, or manually update `mip.SEIP` in an M-mode interrupt handler.
79+
If any UART interrupt is pending, `mip.MEIP` will become pending. To make UART interrupts visible to S-mode, M-mode software must either delegate `mip.MEIP` via `mideleg`, or manually update `mip.SEIP` in an M-mode interrupt handler. The interrupt for a given port is cleared when any register for that port is accessed.
9080

9181
Internally, UART interrupts are implemented using the `uart_flags` variable.
9282

93-
| 31:24 | 23:16 | 15:8 | 7:0 |
94-
| ----- | ----- | ----- | ----- |
95-
| UART3 | UART2 | UART1 | UART0 |
96-
97-
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
98-
| ----------- | ------------ | ------------ | ----------- | ----------- | ------------ | ------------ | ----------- |
99-
| MSI pending | RLSI pending | THRI pending | RDI pending | MSI enabled | RLSI enabled | THRI enabled | RDI enabled |
83+
| 7:4 | 3:0 |
84+
| ---- | ---- |
85+
| `ie` | `ip` |
10086

101-
| Interrupt | Description |
102-
| --------- | ---------------------------------- |
103-
| MSI | Modem Status |
104-
| RLSI | Receiver Line Status |
105-
| THRI | Transmitter Holding Register Empty |
106-
| RDI | Receiver Data Ready |
87+
`ip` and `ie` are similar to the RISC-V `mie` and `mip` registers. UART _i_ corresponds with bit _i_ in both `ip` and `ie`.
10788

10889
### Syscon
10990

asm/print.s

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ _start:
77
# UART0
88
li a0, 0xf0000010
99

10-
li t0, 0b111
11-
sb t0, 8(a0) # FCR
10+
li t0, 0b11
11+
sb t0, 0xc(a0) # control
1212

1313
loop:
1414
lbu t0, 0(s0)
15-
sb t0, 0(a0) # THR
15+
sb t0, 0x4(a0) # tx
1616

1717
addi s0, s0, 1
1818
addi s1, s1, 1

coremark/mlogv32/ee_printf.c

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -661,42 +661,28 @@ ee_vsprintf(char *buf, const char *fmt, va_list args)
661661
}
662662

663663
typedef struct {
664-
unsigned char rhr_thr[4];
665-
unsigned char ier[4];
666-
unsigned char isr_fcr[4];
667-
unsigned char lcr[4];
668-
unsigned char mcr[4];
669-
unsigned char lsr[4];
670-
unsigned char msr[4];
671-
unsigned char spr[4];
664+
unsigned char rx[4];
665+
unsigned char tx[4];
666+
unsigned char status[4];
667+
unsigned char control[4];
672668
} uart_mmio_t;
673669

674670
#define UART0_BASE ((volatile uart_mmio_t*)(0xf0000010))
675671

676-
#define UART_FIFO_CAPACITY 253
677-
678-
static unsigned int uart0_fifo_size = 0;
679-
680672
void
681673
uart_send_char(char c)
682674
{
683675
volatile uart_mmio_t* uart0 = UART0_BASE;
684676

685-
if (uart0_fifo_size >= UART_FIFO_CAPACITY) {
686-
while ((uart0->lsr[0] & 0b1100000) != 0b1100000) {}
687-
uart0_fifo_size = 0;
688-
}
677+
while (uart0->status[0] & 0b1000) {}
689678

690-
uart0->rhr_thr[0] = c;
691-
uart0_fifo_size += 1;
679+
uart0->tx[0] = c;
692680
}
693681

694682
void init_printf() {
695683
volatile uart_mmio_t* uart0 = UART0_BASE;
696-
uart0->isr_fcr[0] = 0b00000111;
697-
while (uart0->lsr[0] & 0b1) {
698-
uart0->isr_fcr[0] = 0b00000111;
699-
}
684+
685+
uart0->control[0] = 0b11;
700686
}
701687

702688
int
78 Bytes
Binary file not shown.

linux/buildroot/board/mlogv32/dts/mlogv32.dts

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
chassis-type = "embedded";
88

99
chosen {
10-
// SBI: console=hvc
11-
// UART0: console=ttyS0
12-
// for debugging: kgdboc_earlycon=sbi kgdboc=ttyS0 kgdbwait
13-
bootargs = "earlycon=sbi console=ttyS0";
10+
// SBI: earlycon=sbi console=hvc
11+
// UART0: earlycon console=ttyUL0
12+
// for debugging: kgdboc_earlycon=sbi kgdboc=ttyUL0 kgdbwait
13+
bootargs = "earlycon console=ttyUL0";
1414
stdout-path = &uart0;
1515
};
1616

@@ -84,44 +84,43 @@
8484
ranges;
8585

8686
uart0: serial@f0000010 {
87-
compatible = "ns16550a";
88-
reg = <0xf0000010 0x20>;
89-
reg-shift = <2>;
87+
compatible = "xlnx,xps-uartlite-1.00.a";
88+
reg = <0xf0000010 0x10>;
9089
interrupts-extended = <&intc 11>;
91-
clock-frequency = <(38400*16)>;
90+
current-speed = <38400>;
9291
fifo-size = <253>;
93-
no-loopback-test;
94-
// TODO: https://github.com/torvalds/linux/blob/8c2e52ebbe885c7eeaabd3b7ddcdc1246fc400d2/drivers/tty/serial/8250/8250_of.c#L233
92+
xlnx,data-bits = <8>;
93+
xlnx,use-parity = <0>;
9594
};
9695

97-
uart1: serial@f0000030 {
98-
compatible = "ns16550a";
99-
reg = <0xf0000030 0x20>;
100-
reg-shift = <2>;
96+
uart1: serial@f0000020 {
97+
compatible = "xlnx,xps-uartlite-1.00.a";
98+
reg = <0xf0000020 0x10>;
10199
interrupts-extended = <&intc 11>;
102-
clock-frequency = <(38400*16)>;
100+
current-speed = <38400>;
103101
fifo-size = <253>;
104-
no-loopback-test;
102+
xlnx,data-bits = <8>;
103+
xlnx,use-parity = <0>;
105104
};
106105

107-
uart2: serial@f0000050 {
108-
compatible = "ns16550a";
109-
reg = <0xf0000050 0x20>;
110-
reg-shift = <2>;
106+
uart2: serial@f0000030 {
107+
compatible = "xlnx,xps-uartlite-1.00.a";
108+
reg = <0xf0000030 0x10>;
111109
interrupts-extended = <&intc 11>;
112-
clock-frequency = <(38400*16)>;
110+
current-speed = <38400>;
113111
fifo-size = <253>;
114-
no-loopback-test;
112+
xlnx,data-bits = <8>;
113+
xlnx,use-parity = <0>;
115114
};
116115

117-
uart3: serial@f0000070 {
118-
compatible = "ns16550a";
119-
reg = <0xf0000070 0x20>;
120-
reg-shift = <2>;
116+
uart3: serial@f0000040 {
117+
compatible = "xlnx,xps-uartlite-1.00.a";
118+
reg = <0xf0000040 0x10>;
121119
interrupts-extended = <&intc 11>;
122-
clock-frequency = <(38400*16)>;
120+
current-speed = <38400>;
123121
fifo-size = <253>;
124-
no-loopback-test;
122+
xlnx,data-bits = <8>;
123+
xlnx,use-parity = <0>;
125124
};
126125

127126
syscon: syscon@fffffff0 {

linux/buildroot/board/mlogv32/linux.config

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,10 @@ CONFIG_PPP_SYNC_TTY=y
4848
# CONFIG_WLAN is not set
4949
# CONFIG_INPUT_MOUSE is not set
5050
CONFIG_VT_HW_CONSOLE_BINDING=y
51-
CONFIG_SERIAL_8250=y
52-
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
53-
# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
54-
CONFIG_SERIAL_8250_CONSOLE=y
55-
CONFIG_SERIAL_8250_EXTENDED=y
56-
CONFIG_SERIAL_8250_SHARE_IRQ=y
57-
CONFIG_SERIAL_OF_PLATFORM=y
5851
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
52+
CONFIG_SERIAL_UARTLITE=y
53+
CONFIG_SERIAL_UARTLITE_CONSOLE=y
54+
CONFIG_SERIAL_UARTLITE_NR_UARTS=4
5955
CONFIG_HVC_RISCV_SBI=y
6056
# CONFIG_HW_RANDOM is not set
6157
CONFIG_POWER_RESET=y

linux/buildroot/board/mlogv32/zsbl/zsbl.S

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
.section .text
2626
.global _start
2727
_start:
28-
// enable UART
28+
// reset UART0 FIFO
2929
la t0, UART0_BASE
30-
li t1, 1
31-
sb t1, 8(t0)
30+
li t1, 0b11
31+
sb t1, 0xc(t0)
3232

3333
#ifdef USE_PROGRAM_ROM
3434
// initialize icache
@@ -54,8 +54,8 @@ _start:
5454
// wait for UART THR to drain so we don't lose any logs if OpenSBI initializes UART0 in the same tick
5555
la t0, UART0_BASE
5656
1:
57-
lbu t1, 0x14(t0)
58-
andi t1, t1, 0b100000
57+
lbu t1, 0x8(t0)
58+
andi t1, t1, 0b100
5959
beqz t1, 1b
6060

6161
// jump to OpenSBI
@@ -68,7 +68,7 @@ do_print:
6868
1:
6969
lbu t1, 0(a0)
7070
beqz t1, 2f
71-
sb t1, 0(t0)
71+
sb t1, 0x4(t0)
7272
addi a0, a0, 1
7373
j 1b
7474
2:

linux/buildroot/opensbi/platform/mlogv32/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
#
1010
config PLATFORM_MLOGV32
1111
bool
12+
select SERIAL_XILINX_UARTLITE
1213
select TIMER_MTIMER
1314
default y

linux/buildroot/opensbi/platform/mlogv32/objects.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ PLATFORM_RISCV_ISA = rv32ima_zicsr_zifencei_zihintpause
3232
PLATFORM_RISCV_CODE_MODEL = medany
3333

3434
# Space separated list of object file names to be compiled for the platform
35-
platform-objs-y += platform.o uart16550.o
35+
platform-objs-y += platform.o
3636

3737
#
3838
# If the platform support requires a builtin device tree file, the name of

linux/buildroot/opensbi/platform/mlogv32/platform.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@
44
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
55
*/
66

7-
#include "uart16550.h"
8-
97
#include <sbi/riscv_asm.h>
108
#include <sbi/riscv_encoding.h>
119
#include <sbi/sbi_const.h>
1210
#include <sbi/sbi_platform.h>
1311

14-
#include <sbi_utils/serial/uart8250.h>
12+
#include <sbi_utils/serial/xlnx_uartlite.h>
1513
#include <sbi_utils/timer/aclint_mtimer.h>
1614

1715
#define MLOGV32_MTIME_FREQ 1000
@@ -21,10 +19,6 @@
2119
#define MLOGV32_MTIMECMP_SIZE 0x8
2220

2321
#define MLOGV32_UART0_ADDR 0xf0000010
24-
#define MLOGV32_UART_INPUT_FREQ 10000000
25-
#define MLOGV32_UART_BAUDRATE 38400
26-
#define MLOGV32_UART_REG_SHIFT 2 /* stride of 4 bytes */
27-
#define MLOGV32_UART_FIFO_CAPACITY 253
2822

2923
static struct aclint_mtimer_data mtimer = {
3024
.mtime_freq = MLOGV32_MTIME_FREQ,
@@ -44,16 +38,7 @@ static int mlogv32_early_init(bool cold_boot)
4438
if (!cold_boot)
4539
return 0;
4640

47-
return uart16550_init(
48-
MLOGV32_UART0_ADDR,
49-
MLOGV32_UART_INPUT_FREQ,
50-
MLOGV32_UART_BAUDRATE,
51-
MLOGV32_UART_REG_SHIFT,
52-
1,
53-
0,
54-
0,
55-
MLOGV32_UART_FIFO_CAPACITY
56-
);
41+
return xlnx_uartlite_init(MLOGV32_UART0_ADDR);
5742
}
5843

5944
/*

0 commit comments

Comments
 (0)