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