1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2025 SiFive, Inc 4 */ 5 6 #include <drivers/sifive_uart.h> 7 #include <io.h> 8 9 /* SiFive UART register defines */ 10 #define UART_REG_TXFIFO 0x0 11 #define UART_REG_RXFIFO 0x4 12 #define UART_REG_TXCTRL 0x8 13 #define UART_REG_RXCTRL 0xC 14 #define UART_REG_IE 0x10 15 #define UART_REG_IP 0x14 16 #define UART_REG_DIV 0x18 17 18 /* SiFive UART status register bits */ 19 #define UART_TXFIFO_FULL 0x80000000 20 #define UART_RXFIFO_EMPTY 0x80000000 21 #define UART_RXFIFO_DATA 0x000000FF 22 #define UART_TXCTRL_TXEN 0x1 23 #define UART_RXCTRL_RXEN 0x1 24 25 static vaddr_t chip_to_base(struct serial_chip *chip) 26 { 27 struct sifive_uart_data *pd = 28 container_of(chip, struct sifive_uart_data, chip); 29 30 return io_pa_or_va(&pd->base, SIFIVE_UART_REG_SIZE); 31 } 32 33 static void sifive_uart_flush(struct serial_chip *chip) 34 { 35 vaddr_t base = chip_to_base(chip); 36 37 while (io_read32(base + UART_REG_TXFIFO) & UART_TXFIFO_FULL) { 38 /* Wait until transmit FIFO is not full */ 39 ; 40 } 41 } 42 43 static bool sifive_uart_have_rx_data(struct serial_chip *chip) 44 { 45 vaddr_t base = chip_to_base(chip); 46 47 return !(io_read32(base + UART_REG_RXFIFO) & UART_RXFIFO_EMPTY); 48 } 49 50 static int sifive_uart_getchar(struct serial_chip *chip) 51 { 52 vaddr_t base = chip_to_base(chip); 53 54 while (!sifive_uart_have_rx_data(chip)) { 55 /* Wait until data is available in the receive FIFO */ 56 ; 57 } 58 return io_read32(base + UART_REG_RXFIFO) & UART_RXFIFO_DATA; 59 } 60 61 static void sifive_uart_putc(struct serial_chip *chip, int ch) 62 { 63 vaddr_t base = chip_to_base(chip); 64 65 sifive_uart_flush(chip); 66 67 /* Write out character to transmit FIFO */ 68 io_write32(base + UART_REG_TXFIFO, ch); 69 } 70 71 static const struct serial_ops sifive_uart_ops = { 72 .flush = sifive_uart_flush, 73 .getchar = sifive_uart_getchar, 74 .have_rx_data = sifive_uart_have_rx_data, 75 .putc = sifive_uart_putc, 76 }; 77 78 void sifive_uart_init(struct sifive_uart_data *pd, paddr_t base, 79 uint32_t uart_clk, uint32_t baud_rate) 80 { 81 uint32_t divisor = 0; 82 83 pd->base.pa = base; 84 pd->chip.ops = &sifive_uart_ops; 85 86 /* Configure baudrate */ 87 if (uart_clk && baud_rate) { 88 divisor = (uart_clk + baud_rate - 1) / baud_rate - 1; 89 io_write32(base + UART_REG_DIV, divisor); 90 } 91 92 /* Disable interrupts */ 93 io_write32(base + UART_REG_IE, 0); 94 95 /* Enable TX */ 96 io_write32(base + UART_REG_TXCTRL, UART_TXCTRL_TXEN); 97 98 /* Enable RX */ 99 io_write32(base + UART_REG_RXCTRL, UART_RXCTRL_RXEN); 100 } 101