1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 */ 5 #include <assert.h> 6 #include <drivers/hi16xx_uart.h> 7 #include <io.h> 8 #include <keep.h> 9 #include <mm/core_mmu.h> 10 #include <util.h> 11 12 /* Register offsets */ 13 14 #define UART_RBR 0x00 /* RX data buffer register */ 15 #define UART_THR 0x00 /* TX data buffer register */ 16 #define UART_DLL 0x00 /* Lower-bit frequency divider register */ 17 18 #define UART_IEL 0x04 /* Interrupt enable register */ 19 #define UART_DLH 0x04 /* Upper-bit frequency divider register */ 20 21 #define UART_FCR 0x08 /* FIFO control register */ 22 23 #define UART_LCR 0x0C /* Line control register */ 24 25 #define UART_LSR 0x14 /* Line status register */ 26 27 #define UART_USR 0x7C /* Status register */ 28 29 /* 30 * Line control register 31 */ 32 33 /* Data length selection */ 34 #define UART_LCR_DLS5 0x0 /* 5 bits */ 35 #define UART_LCR_DLS6 0x1 /* 6 bits */ 36 #define UART_LCR_DLS7 0x2 /* 7 bits */ 37 #define UART_LCR_DLS8 0x3 /* 8 bits */ 38 39 /* Enable access to UART_DLL and UART_DLH */ 40 #define UART_LCR_DLAB 0x80 41 42 /* 43 * FIFO control register 44 */ 45 46 #define UART_FCR_FIFO_EN 0x1 /* Enable FIFO (depth: 32 bytes) */ 47 #define UART_FCR_RX_FIFO_RST 0x2 /* Clear receive FIFO (auto reset) */ 48 #define UART_FCR_TX_FIFO_RST 0x4 /* Clear send FIFO (auto reset) */ 49 50 51 /* 52 * Status register 53 */ 54 55 #define UART_USR_BUSY_BIT 0 /* 0: idle/non-activated, 1: busy */ 56 #define UART_USR_TFNF_BIT 1 /* Transmit FIFO not full bit */ 57 #define UART_USR_TFE_BIT 2 /* Transmit FIFO empty bit */ 58 #define UART_USR_RFNE_BIT 3 /* Receive FIFO not empty bit */ 59 #define UART_USR_RFF_BIT 4 /* Receive FIFO full bit */ 60 61 static vaddr_t chip_to_base(struct serial_chip *chip) 62 { 63 struct hi16xx_uart_data *pd = 64 container_of(chip, struct hi16xx_uart_data, chip); 65 66 return io_pa_or_va(&pd->base); 67 } 68 69 static void hi16xx_uart_flush(struct serial_chip *chip) 70 { 71 vaddr_t base = chip_to_base(chip); 72 73 while (!(io_read32(base + UART_USR) & UART_USR_TFE_BIT)) 74 ; 75 } 76 77 static void hi16xx_uart_putc(struct serial_chip *chip, int ch) 78 { 79 vaddr_t base = chip_to_base(chip); 80 81 /* Wait until TX FIFO is empty */ 82 while (!(io_read32(base + UART_USR) & UART_USR_TFE_BIT)) 83 ; 84 85 /* Put character into TX FIFO */ 86 io_write32(base + UART_THR, ch & 0xFF); 87 } 88 89 static bool hi16xx_uart_have_rx_data(struct serial_chip *chip) 90 { 91 vaddr_t base = chip_to_base(chip); 92 93 return (io_read32(base + UART_USR) & UART_USR_RFNE_BIT); 94 } 95 96 static int hi16xx_uart_getchar(struct serial_chip *chip) 97 { 98 vaddr_t base = chip_to_base(chip); 99 100 while (!hi16xx_uart_have_rx_data(chip)) 101 ; 102 return io_read32(base + UART_RBR) & 0xFF; 103 } 104 105 static const struct serial_ops hi16xx_uart_ops = { 106 .flush = hi16xx_uart_flush, 107 .getchar = hi16xx_uart_getchar, 108 .have_rx_data = hi16xx_uart_have_rx_data, 109 .putc = hi16xx_uart_putc, 110 }; 111 KEEP_PAGER(hi16xx_uart_ops); 112 113 void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base, 114 uint32_t uart_clk, uint32_t baud_rate) 115 { 116 uint16_t freq_div = uart_clk / (16 * baud_rate); 117 118 pd->base.pa = base; 119 pd->chip.ops = &hi16xx_uart_ops; 120 121 /* Enable (and clear) FIFOs */ 122 io_write32(base + UART_FCR, UART_FCR_FIFO_EN); 123 124 /* Enable access to _DLL and _DLH */ 125 io_write32(base + UART_LCR, UART_LCR_DLAB); 126 127 /* Calculate and set UART_DLL */ 128 io_write32(base + UART_DLL, freq_div & 0xFF); 129 130 /* Calculate and set UART_DLH */ 131 io_write32(base + UART_DLH, (freq_div >> 8) & 0xFF); 132 133 /* Clear _DLL/_DLH access bit, set data size (8 bits), parity etc. */ 134 io_write32(base + UART_LCR, UART_LCR_DLS8); 135 136 /* Disable interrupt mode */ 137 io_write32(base + UART_IEL, 0); 138 139 hi16xx_uart_flush(&pd->chip); 140 } 141 142