11537d62eSAijun Sun /* 21537d62eSAijun Sun * Copyright (c) 2016, Spreadtrum Communications Inc. 359cfa779SJerome 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> 2959cfa779SJerome Forissier #include <io.h> 30*8d94060aSEtienne Carriere #include <keep.h> 3159cfa779SJerome Forissier #include <util.h> 321537d62eSAijun Sun 331537d62eSAijun Sun /* Register definitions */ 341537d62eSAijun Sun #define UART_TXD 0x0000 351537d62eSAijun Sun #define UART_RXD 0x0004 361537d62eSAijun Sun #define UART_STS1 0x000C /* data number in TX and RX fifo */ 371537d62eSAijun Sun 381537d62eSAijun Sun /* Register Bit Fields*/ 391537d62eSAijun Sun #define STS1_RXF_CNT_MASK 0x00ff /* Rx FIFO data counter mask */ 401537d62eSAijun Sun #define STS1_TXF_CNT_MASK 0xff00 /* Tx FIFO data counter mask */ 411537d62eSAijun Sun 4259cfa779SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip) 431537d62eSAijun Sun { 4459cfa779SJerome Forissier struct sprd_uart_data *pd = 4559cfa779SJerome Forissier container_of(chip, struct sprd_uart_data, chip); 4659cfa779SJerome Forissier 4759cfa779SJerome Forissier return io_pa_or_va(&pd->base); 481537d62eSAijun Sun } 491537d62eSAijun Sun 5059cfa779SJerome Forissier static void sprd_uart_flush(struct serial_chip *chip) 511537d62eSAijun Sun { 5259cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 531537d62eSAijun Sun 5459cfa779SJerome Forissier while (read32(base + UART_STS1) & STS1_TXF_CNT_MASK) 551537d62eSAijun Sun ; 561537d62eSAijun Sun } 571537d62eSAijun Sun 5859cfa779SJerome Forissier static bool sprd_uart_have_rx_data(struct serial_chip *chip) 591537d62eSAijun Sun { 6059cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 6159cfa779SJerome Forissier 6259cfa779SJerome Forissier return !!(read32(base + UART_STS1) & STS1_RXF_CNT_MASK); 6359cfa779SJerome Forissier } 6459cfa779SJerome Forissier 6559cfa779SJerome Forissier static void sprd_uart_putc(struct serial_chip *chip, int ch) 6659cfa779SJerome Forissier { 6759cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 6859cfa779SJerome Forissier 6959cfa779SJerome Forissier sprd_uart_flush(chip); 7059cfa779SJerome Forissier write32(base + UART_TXD, ch); 7159cfa779SJerome Forissier } 7259cfa779SJerome Forissier 7359cfa779SJerome Forissier static int sprd_uart_getchar(struct serial_chip *chip) 7459cfa779SJerome Forissier { 7559cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 7659cfa779SJerome Forissier 7759cfa779SJerome Forissier while (!sprd_uart_have_rx_data(chip)) 781537d62eSAijun Sun ; 7959cfa779SJerome Forissier 8059cfa779SJerome Forissier return read32(base + UART_RXD) & 0xff; 811537d62eSAijun Sun } 821537d62eSAijun Sun 8359cfa779SJerome Forissier static const struct serial_ops sprd_uart_ops = { 8459cfa779SJerome Forissier .flush = sprd_uart_flush, 8559cfa779SJerome Forissier .getchar = sprd_uart_getchar, 8659cfa779SJerome Forissier .have_rx_data = sprd_uart_have_rx_data, 8759cfa779SJerome Forissier .putc = sprd_uart_putc, 8859cfa779SJerome Forissier }; 89*8d94060aSEtienne Carriere KEEP_PAGER(sprd_uart_ops); 9059cfa779SJerome Forissier 9159cfa779SJerome Forissier void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base) 921537d62eSAijun Sun { 9359cfa779SJerome Forissier pd->base.pa = base; 9459cfa779SJerome Forissier pd->chip.ops = &sprd_uart_ops; 951537d62eSAijun Sun } 96