1 /* 2 * Copyright (c) 2016, Xilinx Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 #include <assert.h> 28 #include <drivers/cdns_uart.h> 29 #include <io.h> 30 #include <mm/core_mmu.h> 31 #include <util.h> 32 33 #define CDNS_UART_CONTROL 0 34 #define CDNS_UART_MODE 4 35 #define CDNS_UART_IEN 8 36 #define CDNS_UART_IRQ_STATUS 0x14 37 #define CDNS_UART_CHANNEL_STATUS 0x2c 38 #define CDNS_UART_FIFO 0x30 39 40 #define CDNS_UART_CONTROL_RXRES BIT(0) 41 #define CDNS_UART_CONTROL_TXRES BIT(1) 42 #define CDNS_UART_CONTROL_RXEN BIT(2) 43 #define CDNS_UART_CONTROL_TXEN BIT(4) 44 45 #define CDNS_UART_MODE_8BIT (0 << 1) 46 #define CDNS_UART_MODE_PARITY_NONE (0x4 << 3) 47 #define CDNS_UART_MODE_1STP (0 << 6) 48 49 #define CDNS_UART_CHANNEL_STATUS_TFUL BIT(4) 50 #define CDNS_UART_CHANNEL_STATUS_TEMPTY BIT(3) 51 #define CDNS_UART_CHANNEL_STATUS_REMPTY BIT(1) 52 53 #define CDNS_UART_IRQ_RXTRIG BIT(0) 54 #define CDNS_UART_IRQ_RXTOUT BIT(8) 55 56 static vaddr_t chip_to_base(struct serial_chip *chip) 57 { 58 struct cdns_uart_data *pd = 59 container_of(chip, struct cdns_uart_data, chip); 60 61 return io_pa_or_va(&pd->base); 62 } 63 64 static void cdns_uart_flush(struct serial_chip *chip) 65 { 66 vaddr_t base = chip_to_base(chip); 67 68 while (!(read32(base + CDNS_UART_CHANNEL_STATUS) & 69 CDNS_UART_CHANNEL_STATUS_TEMPTY)) 70 ; 71 } 72 73 static bool cdns_uart_have_rx_data(struct serial_chip *chip) 74 { 75 vaddr_t base = chip_to_base(chip); 76 77 return !(read32(base + CDNS_UART_CHANNEL_STATUS) & 78 CDNS_UART_CHANNEL_STATUS_REMPTY); 79 } 80 81 static int cdns_uart_getchar(struct serial_chip *chip) 82 { 83 vaddr_t base = chip_to_base(chip); 84 85 while (!cdns_uart_have_rx_data(chip)) 86 ; 87 return read32(base + CDNS_UART_FIFO) & 0xff; 88 } 89 90 static void cdns_uart_putc(struct serial_chip *chip, int ch) 91 { 92 vaddr_t base = chip_to_base(chip); 93 94 /* Wait until there is space in the FIFO */ 95 while (read32(base + CDNS_UART_CHANNEL_STATUS) & 96 CDNS_UART_CHANNEL_STATUS_TFUL) 97 ; 98 99 /* Send the character */ 100 write32(ch, base + CDNS_UART_FIFO); 101 } 102 103 104 static const struct serial_ops cdns_uart_ops = { 105 .flush = cdns_uart_flush, 106 .getchar = cdns_uart_getchar, 107 .have_rx_data = cdns_uart_have_rx_data, 108 .putc = cdns_uart_putc, 109 }; 110 111 /* 112 * we rely on the bootloader having set up the HW correctly, we just enable 113 * transmitter/receiver here, just in case. 114 */ 115 void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, 116 uint32_t baud_rate) 117 { 118 pd->base.pa = base; 119 pd->chip.ops = &cdns_uart_ops; 120 121 if (!uart_clk || !baud_rate) 122 return; 123 124 /* Enable UART and RX/TX */ 125 write32(CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN, 126 base + CDNS_UART_CONTROL); 127 128 cdns_uart_flush(&pd->chip); 129 } 130