11537d62eSAijun Sun /* 21537d62eSAijun Sun * Copyright (c) 2016, Spreadtrum Communications Inc. 3*59cfa779SJerome Forissier * Copyright (c) 2017, Linaro Limited 41537d62eSAijun Sun * All rights reserved. 51537d62eSAijun Sun * 61537d62eSAijun Sun * Redistribution and use in source and binary forms, with or without 71537d62eSAijun Sun * modification, are permitted provided that the following conditions are met: 81537d62eSAijun Sun * 91537d62eSAijun Sun * 1. Redistributions of source code must retain the above copyright notice, 101537d62eSAijun Sun * this list of conditions and the following disclaimer. 111537d62eSAijun Sun * 121537d62eSAijun Sun * 2. Redistributions in binary form must reproduce the above copyright notice, 131537d62eSAijun Sun * this list of conditions and the following disclaimer in the documentation 141537d62eSAijun Sun * and/or other materials provided with the distribution. 151537d62eSAijun Sun * 161537d62eSAijun Sun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 171537d62eSAijun Sun * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 181537d62eSAijun Sun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191537d62eSAijun Sun * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 201537d62eSAijun Sun * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211537d62eSAijun Sun * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221537d62eSAijun Sun * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231537d62eSAijun Sun * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241537d62eSAijun Sun * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251537d62eSAijun Sun * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261537d62eSAijun Sun * POSSIBILITY OF SUCH DAMAGE. 271537d62eSAijun Sun */ 281537d62eSAijun Sun #include <drivers/sprd_uart.h> 29*59cfa779SJerome Forissier #include <io.h> 30*59cfa779SJerome Forissier #include <util.h> 311537d62eSAijun Sun 321537d62eSAijun Sun /* Register definitions */ 331537d62eSAijun Sun #define UART_TXD 0x0000 341537d62eSAijun Sun #define UART_RXD 0x0004 351537d62eSAijun Sun #define UART_STS1 0x000C /* data number in TX and RX fifo */ 361537d62eSAijun Sun 371537d62eSAijun Sun /* Register Bit Fields*/ 381537d62eSAijun Sun #define STS1_RXF_CNT_MASK 0x00ff /* Rx FIFO data counter mask */ 391537d62eSAijun Sun #define STS1_TXF_CNT_MASK 0xff00 /* Tx FIFO data counter mask */ 401537d62eSAijun Sun 41*59cfa779SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip) 421537d62eSAijun Sun { 43*59cfa779SJerome Forissier struct sprd_uart_data *pd = 44*59cfa779SJerome Forissier container_of(chip, struct sprd_uart_data, chip); 45*59cfa779SJerome Forissier 46*59cfa779SJerome Forissier return io_pa_or_va(&pd->base); 471537d62eSAijun Sun } 481537d62eSAijun Sun 49*59cfa779SJerome Forissier static void sprd_uart_flush(struct serial_chip *chip) 501537d62eSAijun Sun { 51*59cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 521537d62eSAijun Sun 53*59cfa779SJerome Forissier while (read32(base + UART_STS1) & STS1_TXF_CNT_MASK) 541537d62eSAijun Sun ; 551537d62eSAijun Sun } 561537d62eSAijun Sun 57*59cfa779SJerome Forissier static bool sprd_uart_have_rx_data(struct serial_chip *chip) 581537d62eSAijun Sun { 59*59cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 60*59cfa779SJerome Forissier 61*59cfa779SJerome Forissier return !!(read32(base + UART_STS1) & STS1_RXF_CNT_MASK); 62*59cfa779SJerome Forissier } 63*59cfa779SJerome Forissier 64*59cfa779SJerome Forissier static void sprd_uart_putc(struct serial_chip *chip, int ch) 65*59cfa779SJerome Forissier { 66*59cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 67*59cfa779SJerome Forissier 68*59cfa779SJerome Forissier sprd_uart_flush(chip); 69*59cfa779SJerome Forissier write32(base + UART_TXD, ch); 70*59cfa779SJerome Forissier } 71*59cfa779SJerome Forissier 72*59cfa779SJerome Forissier static int sprd_uart_getchar(struct serial_chip *chip) 73*59cfa779SJerome Forissier { 74*59cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 75*59cfa779SJerome Forissier 76*59cfa779SJerome Forissier while (!sprd_uart_have_rx_data(chip)) 771537d62eSAijun Sun ; 78*59cfa779SJerome Forissier 79*59cfa779SJerome Forissier return read32(base + UART_RXD) & 0xff; 801537d62eSAijun Sun } 811537d62eSAijun Sun 82*59cfa779SJerome Forissier static const struct serial_ops sprd_uart_ops = { 83*59cfa779SJerome Forissier .flush = sprd_uart_flush, 84*59cfa779SJerome Forissier .getchar = sprd_uart_getchar, 85*59cfa779SJerome Forissier .have_rx_data = sprd_uart_have_rx_data, 86*59cfa779SJerome Forissier .putc = sprd_uart_putc, 87*59cfa779SJerome Forissier }; 88*59cfa779SJerome Forissier 89*59cfa779SJerome Forissier void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base) 901537d62eSAijun Sun { 91*59cfa779SJerome Forissier pd->base.pa = base; 92*59cfa779SJerome Forissier pd->chip.ops = &sprd_uart_ops; 931537d62eSAijun Sun } 94