11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 21537d62eSAijun Sun /* 31537d62eSAijun Sun * Copyright (c) 2016, Spreadtrum Communications Inc. 459cfa779SJerome Forissier * Copyright (c) 2017, Linaro Limited 51537d62eSAijun Sun * All rights reserved. 61537d62eSAijun Sun * 71537d62eSAijun Sun * Redistribution and use in source and binary forms, with or without 81537d62eSAijun Sun * modification, are permitted provided that the following conditions are met: 91537d62eSAijun Sun * 101537d62eSAijun Sun * 1. Redistributions of source code must retain the above copyright notice, 111537d62eSAijun Sun * this list of conditions and the following disclaimer. 121537d62eSAijun Sun * 131537d62eSAijun Sun * 2. Redistributions in binary form must reproduce the above copyright notice, 141537d62eSAijun Sun * this list of conditions and the following disclaimer in the documentation 151537d62eSAijun Sun * and/or other materials provided with the distribution. 161537d62eSAijun Sun * 171537d62eSAijun Sun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 181537d62eSAijun Sun * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191537d62eSAijun Sun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201537d62eSAijun Sun * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 211537d62eSAijun Sun * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 221537d62eSAijun Sun * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 231537d62eSAijun Sun * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 241537d62eSAijun Sun * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 251537d62eSAijun Sun * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 261537d62eSAijun Sun * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 271537d62eSAijun Sun * POSSIBILITY OF SUCH DAMAGE. 281537d62eSAijun Sun */ 291537d62eSAijun Sun #include <drivers/sprd_uart.h> 3059cfa779SJerome Forissier #include <io.h> 318d94060aSEtienne Carriere #include <keep.h> 3259cfa779SJerome Forissier #include <util.h> 331537d62eSAijun Sun 341537d62eSAijun Sun /* Register definitions */ 351537d62eSAijun Sun #define UART_TXD 0x0000 361537d62eSAijun Sun #define UART_RXD 0x0004 371537d62eSAijun Sun #define UART_STS1 0x000C /* data number in TX and RX fifo */ 381537d62eSAijun Sun 391537d62eSAijun Sun /* Register Bit Fields*/ 401537d62eSAijun Sun #define STS1_RXF_CNT_MASK 0x00ff /* Rx FIFO data counter mask */ 411537d62eSAijun Sun #define STS1_TXF_CNT_MASK 0xff00 /* Tx FIFO data counter mask */ 421537d62eSAijun Sun 4359cfa779SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip) 441537d62eSAijun Sun { 4559cfa779SJerome Forissier struct sprd_uart_data *pd = 4659cfa779SJerome Forissier container_of(chip, struct sprd_uart_data, chip); 4759cfa779SJerome Forissier 4859cfa779SJerome Forissier return io_pa_or_va(&pd->base); 491537d62eSAijun Sun } 501537d62eSAijun Sun 5159cfa779SJerome Forissier static void sprd_uart_flush(struct serial_chip *chip) 521537d62eSAijun Sun { 5359cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 541537d62eSAijun Sun 55*918bb3a5SEtienne Carriere while (io_read32(base + UART_STS1) & STS1_TXF_CNT_MASK) 561537d62eSAijun Sun ; 571537d62eSAijun Sun } 581537d62eSAijun Sun 5959cfa779SJerome Forissier static bool sprd_uart_have_rx_data(struct serial_chip *chip) 601537d62eSAijun Sun { 6159cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 6259cfa779SJerome Forissier 63*918bb3a5SEtienne Carriere return !!(io_read32(base + UART_STS1) & STS1_RXF_CNT_MASK); 6459cfa779SJerome Forissier } 6559cfa779SJerome Forissier 6659cfa779SJerome Forissier static void sprd_uart_putc(struct serial_chip *chip, int ch) 6759cfa779SJerome Forissier { 6859cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 6959cfa779SJerome Forissier 7059cfa779SJerome Forissier sprd_uart_flush(chip); 71*918bb3a5SEtienne Carriere io_write32(base + UART_TXD, ch); 7259cfa779SJerome Forissier } 7359cfa779SJerome Forissier 7459cfa779SJerome Forissier static int sprd_uart_getchar(struct serial_chip *chip) 7559cfa779SJerome Forissier { 7659cfa779SJerome Forissier vaddr_t base = chip_to_base(chip); 7759cfa779SJerome Forissier 7859cfa779SJerome Forissier while (!sprd_uart_have_rx_data(chip)) 791537d62eSAijun Sun ; 8059cfa779SJerome Forissier 81*918bb3a5SEtienne Carriere return io_read32(base + UART_RXD) & 0xff; 821537d62eSAijun Sun } 831537d62eSAijun Sun 8459cfa779SJerome Forissier static const struct serial_ops sprd_uart_ops = { 8559cfa779SJerome Forissier .flush = sprd_uart_flush, 8659cfa779SJerome Forissier .getchar = sprd_uart_getchar, 8759cfa779SJerome Forissier .have_rx_data = sprd_uart_have_rx_data, 8859cfa779SJerome Forissier .putc = sprd_uart_putc, 8959cfa779SJerome Forissier }; 908d94060aSEtienne Carriere KEEP_PAGER(sprd_uart_ops); 9159cfa779SJerome Forissier 9259cfa779SJerome Forissier void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base) 931537d62eSAijun Sun { 9459cfa779SJerome Forissier pd->base.pa = base; 9559cfa779SJerome Forissier pd->chip.ops = &sprd_uart_ops; 961537d62eSAijun Sun } 97