1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, GlobalLogic 4 * Copyright (c) 2017, Linaro Limited 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 #include <drivers/scif.h> 30 #include <io.h> 31 #include <keep.h> 32 #include <util.h> 33 34 #define SCIF_SCSCR (0x08) 35 #define SCIF_SCFSR (0x10) 36 #define SCIF_SCFTDR (0x0C) 37 #define SCIF_SCFCR (0x18) 38 #define SCIF_SCFDR (0x1C) 39 40 #define SCSCR_TE BIT(5) 41 #define SCFSR_TDFE BIT(5) 42 #define SCFSR_TEND BIT(6) 43 44 #define SCFDR_T_SHIFT 8 45 46 #define SCIF_TX_FIFO_SIZE 16 47 48 static vaddr_t chip_to_base(struct serial_chip *chip) 49 { 50 struct scif_uart_data *pd = 51 container_of(chip, struct scif_uart_data, chip); 52 53 return io_pa_or_va(&pd->base, SCIF_REG_SIZE); 54 } 55 56 static void scif_uart_flush(struct serial_chip *chip) 57 { 58 vaddr_t base = chip_to_base(chip); 59 60 while (!(io_read16(base + SCIF_SCFSR) & SCFSR_TEND)) 61 ; 62 } 63 64 static void scif_uart_putc(struct serial_chip *chip, int ch) 65 { 66 vaddr_t base = chip_to_base(chip); 67 68 /* Wait until there is space in the FIFO */ 69 while ((io_read16(base + SCIF_SCFDR) >> SCFDR_T_SHIFT) >= 70 SCIF_TX_FIFO_SIZE) 71 ; 72 io_write8(base + SCIF_SCFTDR, ch); 73 io_clrbits16(base + SCIF_SCFSR, SCFSR_TEND | SCFSR_TDFE); 74 } 75 76 static const struct serial_ops scif_uart_ops = { 77 .flush = scif_uart_flush, 78 .putc = scif_uart_putc, 79 }; 80 DECLARE_KEEP_PAGER(scif_uart_ops); 81 82 void scif_uart_init(struct scif_uart_data *pd, paddr_t pbase) 83 { 84 vaddr_t base; 85 86 pd->base.pa = pbase; 87 pd->chip.ops = &scif_uart_ops; 88 89 base = io_pa_or_va(&pd->base, SCIF_REG_SIZE); 90 91 /* Set Transmit Enable in Control register */ 92 io_setbits16(base + SCIF_SCSCR, SCSCR_TE); 93 94 scif_uart_flush(&pd->chip); 95 } 96