1*1bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 244bd24c5SJames Kung /* 344bd24c5SJames Kung * Copyright (c) 2015, Linaro Limited 444bd24c5SJames Kung * All rights reserved. 544bd24c5SJames Kung * 644bd24c5SJames Kung * Redistribution and use in source and binary forms, with or without 744bd24c5SJames Kung * modification, are permitted provided that the following conditions are met: 844bd24c5SJames Kung * 944bd24c5SJames Kung * 1. Redistributions of source code must retain the above copyright notice, 1044bd24c5SJames Kung * this list of conditions and the following disclaimer. 1144bd24c5SJames Kung * 1244bd24c5SJames Kung * 2. Redistributions in binary form must reproduce the above copyright notice, 1344bd24c5SJames Kung * this list of conditions and the following disclaimer in the documentation 1444bd24c5SJames Kung * and/or other materials provided with the distribution. 1544bd24c5SJames Kung * 1644bd24c5SJames Kung * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1744bd24c5SJames Kung * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1844bd24c5SJames Kung * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1944bd24c5SJames Kung * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2044bd24c5SJames Kung * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2144bd24c5SJames Kung * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2244bd24c5SJames Kung * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2344bd24c5SJames Kung * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2444bd24c5SJames Kung * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2544bd24c5SJames Kung * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2644bd24c5SJames Kung * POSSIBILITY OF SUCH DAMAGE. 2744bd24c5SJames Kung */ 2844bd24c5SJames Kung 29d66fa083SJerome Forissier #include <compiler.h> 3044bd24c5SJames Kung #include <console.h> 318d94060aSEtienne Carriere #include <drivers/serial8250_uart.h> 3244bd24c5SJames Kung #include <io.h> 338d94060aSEtienne Carriere #include <keep.h> 34d66fa083SJerome Forissier #include <util.h> 3544bd24c5SJames Kung 3644bd24c5SJames Kung /* uart register defines */ 3744bd24c5SJames Kung #define UART_RHR 0x0 3844bd24c5SJames Kung #define UART_THR 0x0 3944bd24c5SJames Kung #define UART_IER 0x4 4044bd24c5SJames Kung #define UART_ISR 0x8 4144bd24c5SJames Kung #define UART_FCR 0x8 4244bd24c5SJames Kung #define UART_LCR 0xc 4344bd24c5SJames Kung #define UART_MCR 0x10 4444bd24c5SJames Kung #define UART_LSR 0x14 4544bd24c5SJames Kung #define UART_MSR 0x18 4644bd24c5SJames Kung #define UART_SPR 0x1c 4744bd24c5SJames Kung 4844bd24c5SJames Kung /* uart status register bits */ 4944bd24c5SJames Kung #define LSR_TEMT 0x40 /* Transmitter empty */ 5044bd24c5SJames Kung #define LSR_THRE 0x20 /* Transmit-hold-register empty */ 5144bd24c5SJames Kung #define LSR_EMPTY (LSR_TEMT | LSR_THRE) 5244bd24c5SJames Kung #define LSR_DR 0x01 /* DATA Ready */ 5344bd24c5SJames Kung 54d66fa083SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip) 5544bd24c5SJames Kung { 56d66fa083SJerome Forissier struct serial8250_uart_data *pd = 57d66fa083SJerome Forissier container_of(chip, struct serial8250_uart_data, chip); 58d66fa083SJerome Forissier 59d66fa083SJerome Forissier return io_pa_or_va(&pd->base); 6044bd24c5SJames Kung } 6144bd24c5SJames Kung 62d66fa083SJerome Forissier static void serial8250_uart_flush(struct serial_chip *chip) 6344bd24c5SJames Kung { 64d66fa083SJerome Forissier vaddr_t base = chip_to_base(chip); 65d66fa083SJerome Forissier 6644bd24c5SJames Kung while (1) { 6765d34b1fSJoseph Chen uint32_t state = read32(base + UART_LSR); 6844bd24c5SJames Kung 69d66fa083SJerome Forissier /* Wait until transmit FIFO is empty */ 7044bd24c5SJames Kung if ((state & LSR_EMPTY) == LSR_EMPTY) 7144bd24c5SJames Kung break; 7244bd24c5SJames Kung } 7344bd24c5SJames Kung } 7444bd24c5SJames Kung 75d66fa083SJerome Forissier static bool serial8250_uart_have_rx_data(struct serial_chip *chip) 7644bd24c5SJames Kung { 77d66fa083SJerome Forissier vaddr_t base = chip_to_base(chip); 78d66fa083SJerome Forissier 7944bd24c5SJames Kung return (read32(base + UART_LSR) & LSR_DR); 8044bd24c5SJames Kung } 8144bd24c5SJames Kung 82d66fa083SJerome Forissier static int serial8250_uart_getchar(struct serial_chip *chip) 8344bd24c5SJames Kung { 84d66fa083SJerome Forissier vaddr_t base = chip_to_base(chip); 8544bd24c5SJames Kung 86d66fa083SJerome Forissier while (!serial8250_uart_have_rx_data(chip)) { 87d66fa083SJerome Forissier /* Transmit FIFO is empty, waiting again */ 8844bd24c5SJames Kung ; 8944bd24c5SJames Kung } 9065d34b1fSJoseph Chen return read32(base + UART_RHR) & 0xff; 9144bd24c5SJames Kung } 9244bd24c5SJames Kung 93d66fa083SJerome Forissier static void serial8250_uart_putc(struct serial_chip *chip, int ch) 94d66fa083SJerome Forissier { 95d66fa083SJerome Forissier vaddr_t base = chip_to_base(chip); 96d66fa083SJerome Forissier 97d66fa083SJerome Forissier serial8250_uart_flush(chip); 98d66fa083SJerome Forissier 99d66fa083SJerome Forissier /* Write out character to transmit FIFO */ 10065d34b1fSJoseph Chen write32(ch, base + UART_THR); 101d66fa083SJerome Forissier } 102d66fa083SJerome Forissier 103d66fa083SJerome Forissier static const struct serial_ops serial8250_uart_ops = { 104d66fa083SJerome Forissier .flush = serial8250_uart_flush, 105d66fa083SJerome Forissier .getchar = serial8250_uart_getchar, 106d66fa083SJerome Forissier .have_rx_data = serial8250_uart_have_rx_data, 107d66fa083SJerome Forissier .putc = serial8250_uart_putc, 108d66fa083SJerome Forissier }; 1098d94060aSEtienne Carriere KEEP_PAGER(serial8250_uart_ops); 110d66fa083SJerome Forissier 111d66fa083SJerome Forissier void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base, 112d66fa083SJerome Forissier uint32_t __unused uart_clk, 113d66fa083SJerome Forissier uint32_t __unused baud_rate) 114d66fa083SJerome Forissier 115d66fa083SJerome Forissier { 116d66fa083SJerome Forissier pd->base.pa = base; 117d66fa083SJerome Forissier pd->chip.ops = &serial8250_uart_ops; 118d66fa083SJerome Forissier 119d66fa083SJerome Forissier /* 120d66fa083SJerome Forissier * do nothing, debug uart(uart0) share with normal world, 121d66fa083SJerome Forissier * everything for uart0 is ready now. 122d66fa083SJerome Forissier */ 123d66fa083SJerome Forissier } 124