13481d2f6SSoren Brinkmann /* 23481d2f6SSoren Brinkmann * Copyright (c) 2016, Xilinx Inc. 33481d2f6SSoren Brinkmann * All rights reserved. 43481d2f6SSoren Brinkmann * 53481d2f6SSoren Brinkmann * Redistribution and use in source and binary forms, with or without 63481d2f6SSoren Brinkmann * modification, are permitted provided that the following conditions are met: 73481d2f6SSoren Brinkmann * 83481d2f6SSoren Brinkmann * 1. Redistributions of source code must retain the above copyright notice, 93481d2f6SSoren Brinkmann * this list of conditions and the following disclaimer. 103481d2f6SSoren Brinkmann * 113481d2f6SSoren Brinkmann * 2. Redistributions in binary form must reproduce the above copyright notice, 123481d2f6SSoren Brinkmann * this list of conditions and the following disclaimer in the documentation 133481d2f6SSoren Brinkmann * and/or other materials provided with the distribution. 143481d2f6SSoren Brinkmann * 153481d2f6SSoren Brinkmann * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 163481d2f6SSoren Brinkmann * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 173481d2f6SSoren Brinkmann * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 183481d2f6SSoren Brinkmann * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 193481d2f6SSoren Brinkmann * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 203481d2f6SSoren Brinkmann * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 213481d2f6SSoren Brinkmann * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 223481d2f6SSoren Brinkmann * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 233481d2f6SSoren Brinkmann * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 243481d2f6SSoren Brinkmann * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 253481d2f6SSoren Brinkmann * POSSIBILITY OF SUCH DAMAGE. 263481d2f6SSoren Brinkmann */ 27*62fff454SJerome Forissier #include <assert.h> 283481d2f6SSoren Brinkmann #include <drivers/cdns_uart.h> 293481d2f6SSoren Brinkmann #include <io.h> 30*62fff454SJerome Forissier #include <mm/core_mmu.h> 313481d2f6SSoren Brinkmann #include <util.h> 323481d2f6SSoren Brinkmann 333481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL 0 343481d2f6SSoren Brinkmann #define CDNS_UART_MODE 4 353481d2f6SSoren Brinkmann #define CDNS_UART_IEN 8 363481d2f6SSoren Brinkmann #define CDNS_UART_IRQ_STATUS 0x14 373481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS 0x2c 383481d2f6SSoren Brinkmann #define CDNS_UART_FIFO 0x30 393481d2f6SSoren Brinkmann 403481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_RXRES BIT(0) 413481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_TXRES BIT(1) 423481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_RXEN BIT(2) 433481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_TXEN BIT(4) 443481d2f6SSoren Brinkmann 453481d2f6SSoren Brinkmann #define CDNS_UART_MODE_8BIT (0 << 1) 463481d2f6SSoren Brinkmann #define CDNS_UART_MODE_PARITY_NONE (0x4 << 3) 473481d2f6SSoren Brinkmann #define CDNS_UART_MODE_1STP (0 << 6) 483481d2f6SSoren Brinkmann 493481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS_TFUL BIT(4) 503481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS_TEMPTY BIT(3) 513481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS_REMPTY BIT(1) 523481d2f6SSoren Brinkmann 533481d2f6SSoren Brinkmann #define CDNS_UART_IRQ_RXTRIG BIT(0) 543481d2f6SSoren Brinkmann #define CDNS_UART_IRQ_RXTOUT BIT(8) 553481d2f6SSoren Brinkmann 56*62fff454SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip) 573481d2f6SSoren Brinkmann { 58*62fff454SJerome Forissier struct cdns_uart_data *pd = 59*62fff454SJerome Forissier container_of(chip, struct cdns_uart_data, chip); 60*62fff454SJerome Forissier 61*62fff454SJerome Forissier return io_pa_or_va(&pd->base); 62*62fff454SJerome Forissier } 63*62fff454SJerome Forissier 64*62fff454SJerome Forissier static void cdns_uart_flush(struct serial_chip *chip) 65*62fff454SJerome Forissier { 66*62fff454SJerome Forissier vaddr_t base = chip_to_base(chip); 67*62fff454SJerome Forissier 683481d2f6SSoren Brinkmann while (!(read32(base + CDNS_UART_CHANNEL_STATUS) & 693481d2f6SSoren Brinkmann CDNS_UART_CHANNEL_STATUS_TEMPTY)) 703481d2f6SSoren Brinkmann ; 713481d2f6SSoren Brinkmann } 723481d2f6SSoren Brinkmann 73*62fff454SJerome Forissier static bool cdns_uart_have_rx_data(struct serial_chip *chip) 743481d2f6SSoren Brinkmann { 75*62fff454SJerome Forissier vaddr_t base = chip_to_base(chip); 763481d2f6SSoren Brinkmann 77*62fff454SJerome Forissier return !(read32(base + CDNS_UART_CHANNEL_STATUS) & 78*62fff454SJerome Forissier CDNS_UART_CHANNEL_STATUS_REMPTY); 793481d2f6SSoren Brinkmann } 803481d2f6SSoren Brinkmann 81*62fff454SJerome Forissier static int cdns_uart_getchar(struct serial_chip *chip) 823481d2f6SSoren Brinkmann { 83*62fff454SJerome Forissier vaddr_t base = chip_to_base(chip); 84*62fff454SJerome Forissier 85*62fff454SJerome Forissier while (!cdns_uart_have_rx_data(chip)) 86*62fff454SJerome Forissier ; 87*62fff454SJerome Forissier return read32(base + CDNS_UART_FIFO) & 0xff; 88*62fff454SJerome Forissier } 89*62fff454SJerome Forissier 90*62fff454SJerome Forissier static void cdns_uart_putc(struct serial_chip *chip, int ch) 91*62fff454SJerome Forissier { 92*62fff454SJerome Forissier vaddr_t base = chip_to_base(chip); 93*62fff454SJerome Forissier 943481d2f6SSoren Brinkmann /* Wait until there is space in the FIFO */ 953481d2f6SSoren Brinkmann while (read32(base + CDNS_UART_CHANNEL_STATUS) & 963481d2f6SSoren Brinkmann CDNS_UART_CHANNEL_STATUS_TFUL) 973481d2f6SSoren Brinkmann ; 983481d2f6SSoren Brinkmann 993481d2f6SSoren Brinkmann /* Send the character */ 1003481d2f6SSoren Brinkmann write32(ch, base + CDNS_UART_FIFO); 1013481d2f6SSoren Brinkmann } 1023481d2f6SSoren Brinkmann 1033481d2f6SSoren Brinkmann 104*62fff454SJerome Forissier static const struct serial_ops cdns_uart_ops = { 105*62fff454SJerome Forissier .flush = cdns_uart_flush, 106*62fff454SJerome Forissier .getchar = cdns_uart_getchar, 107*62fff454SJerome Forissier .have_rx_data = cdns_uart_have_rx_data, 108*62fff454SJerome Forissier .putc = cdns_uart_putc, 109*62fff454SJerome Forissier }; 110*62fff454SJerome Forissier 111*62fff454SJerome Forissier /* 112*62fff454SJerome Forissier * we rely on the bootloader having set up the HW correctly, we just enable 113*62fff454SJerome Forissier * transmitter/receiver here, just in case. 114*62fff454SJerome Forissier */ 115*62fff454SJerome Forissier void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, 116*62fff454SJerome Forissier uint32_t baud_rate) 1173481d2f6SSoren Brinkmann { 118*62fff454SJerome Forissier pd->base.pa = base; 119*62fff454SJerome Forissier pd->chip.ops = &cdns_uart_ops; 120*62fff454SJerome Forissier 121*62fff454SJerome Forissier if (!uart_clk || !baud_rate) 122*62fff454SJerome Forissier return; 123*62fff454SJerome Forissier 124*62fff454SJerome Forissier /* Enable UART and RX/TX */ 125*62fff454SJerome Forissier write32(CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN, 126*62fff454SJerome Forissier base + CDNS_UART_CONTROL); 127*62fff454SJerome Forissier 128*62fff454SJerome Forissier cdns_uart_flush(&pd->chip); 1293481d2f6SSoren Brinkmann } 130