11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 28c4a5a9aSPeng Fan /* 38c4a5a9aSPeng Fan * Copyright (C) 2015 Freescale Semiconductor, Inc. 48c4a5a9aSPeng Fan * All rights reserved. 58c4a5a9aSPeng Fan * 68c4a5a9aSPeng Fan * Redistribution and use in source and binary forms, with or without 78c4a5a9aSPeng Fan * modification, are permitted provided that the following conditions are met: 88c4a5a9aSPeng Fan * 98c4a5a9aSPeng Fan * 1. Redistributions of source code must retain the above copyright notice, 108c4a5a9aSPeng Fan * this list of conditions and the following disclaimer. 118c4a5a9aSPeng Fan * 128c4a5a9aSPeng Fan * 2. Redistributions in binary form must reproduce the above copyright notice, 138c4a5a9aSPeng Fan * this list of conditions and the following disclaimer in the documentation 148c4a5a9aSPeng Fan * and/or other materials provided with the distribution. 158c4a5a9aSPeng Fan * 168c4a5a9aSPeng Fan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 178c4a5a9aSPeng Fan * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 188c4a5a9aSPeng Fan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 198c4a5a9aSPeng Fan * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 208c4a5a9aSPeng Fan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 218c4a5a9aSPeng Fan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 228c4a5a9aSPeng Fan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 238c4a5a9aSPeng Fan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 248c4a5a9aSPeng Fan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 258c4a5a9aSPeng Fan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 268c4a5a9aSPeng Fan * POSSIBILITY OF SUCH DAMAGE. 278c4a5a9aSPeng Fan */ 288c4a5a9aSPeng Fan 2926267e82SJerome Forissier #include <assert.h> 308c4a5a9aSPeng Fan #include <drivers/imx_uart.h> 318c4a5a9aSPeng Fan #include <io.h> 328d94060aSEtienne Carriere #include <keep.h> 3326267e82SJerome Forissier #include <util.h> 348c4a5a9aSPeng Fan 358c4a5a9aSPeng Fan /* Register definitions */ 368c4a5a9aSPeng Fan #define URXD 0x0 /* Receiver Register */ 378c4a5a9aSPeng Fan #define UTXD 0x40 /* Transmitter Register */ 388c4a5a9aSPeng Fan #define UCR1 0x80 /* Control Register 1 */ 398c4a5a9aSPeng Fan #define UCR2 0x84 /* Control Register 2 */ 408c4a5a9aSPeng Fan #define UCR3 0x88 /* Control Register 3 */ 418c4a5a9aSPeng Fan #define UCR4 0x8c /* Control Register 4 */ 428c4a5a9aSPeng Fan #define UFCR 0x90 /* FIFO Control Register */ 438c4a5a9aSPeng Fan #define USR1 0x94 /* Status Register 1 */ 448c4a5a9aSPeng Fan #define USR2 0x98 /* Status Register 2 */ 458c4a5a9aSPeng Fan #define UESC 0x9c /* Escape Character Register */ 468c4a5a9aSPeng Fan #define UTIM 0xa0 /* Escape Timer Register */ 478c4a5a9aSPeng Fan #define UBIR 0xa4 /* BRM Incremental Register */ 488c4a5a9aSPeng Fan #define UBMR 0xa8 /* BRM Modulator Register */ 498c4a5a9aSPeng Fan #define UBRC 0xac /* Baud Rate Count Register */ 508c4a5a9aSPeng Fan #define UTS 0xb4 /* UART Test Register (mx31) */ 518c4a5a9aSPeng Fan 528c4a5a9aSPeng Fan /* UART Control Register Bit Fields.*/ 538c4a5a9aSPeng Fan #define URXD_CHARRDY (1<<15) 548c4a5a9aSPeng Fan #define URXD_ERR (1<<14) 558c4a5a9aSPeng Fan #define URXD_OVRRUN (1<<13) 568c4a5a9aSPeng Fan #define URXD_FRMERR (1<<12) 578c4a5a9aSPeng Fan #define URXD_BRK (1<<11) 588c4a5a9aSPeng Fan #define URXD_PRERR (1<<10) 598c4a5a9aSPeng Fan #define URXD_RX_DATA (0xFF) 608c4a5a9aSPeng Fan #define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ 618c4a5a9aSPeng Fan #define UCR1_ADBR (1<<14) /* Auto detect baud rate */ 628c4a5a9aSPeng Fan #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ 638c4a5a9aSPeng Fan #define UCR1_IDEN (1<<12) /* Idle condition interrupt */ 648c4a5a9aSPeng Fan #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ 658c4a5a9aSPeng Fan #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ 668c4a5a9aSPeng Fan #define UCR1_IREN (1<<7) /* Infrared interface enable */ 678c4a5a9aSPeng Fan #define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ 688c4a5a9aSPeng Fan #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ 698c4a5a9aSPeng Fan #define UCR1_SNDBRK (1<<4) /* Send break */ 708c4a5a9aSPeng Fan #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ 718c4a5a9aSPeng Fan #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ 728c4a5a9aSPeng Fan #define UCR1_DOZE (1<<1) /* Doze */ 738c4a5a9aSPeng Fan #define UCR1_UARTEN (1<<0) /* UART enabled */ 748c4a5a9aSPeng Fan 758c4a5a9aSPeng Fan #define UTS_FRCPERR (1<<13) /* Force parity error */ 768c4a5a9aSPeng Fan #define UTS_LOOP (1<<12) /* Loop tx and rx */ 778c4a5a9aSPeng Fan #define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ 788c4a5a9aSPeng Fan #define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ 798c4a5a9aSPeng Fan #define UTS_TXFULL (1<<4) /* TxFIFO full */ 808c4a5a9aSPeng Fan #define UTS_RXFULL (1<<3) /* RxFIFO full */ 818c4a5a9aSPeng Fan #define UTS_SOFTRST (1<<0) /* Software reset */ 828c4a5a9aSPeng Fan 8326267e82SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip) 848c4a5a9aSPeng Fan { 8526267e82SJerome Forissier struct imx_uart_data *pd = 8626267e82SJerome Forissier container_of(chip, struct imx_uart_data, chip); 8726267e82SJerome Forissier 8826267e82SJerome Forissier return io_pa_or_va(&pd->base); 898c4a5a9aSPeng Fan } 908c4a5a9aSPeng Fan 9126267e82SJerome Forissier static void imx_uart_flush(struct serial_chip *chip) 928c4a5a9aSPeng Fan { 9326267e82SJerome Forissier vaddr_t base = chip_to_base(chip); 9426267e82SJerome Forissier 95*21145fe5SJordan Rhee 968c4a5a9aSPeng Fan while (!(read32(base + UTS) & UTS_TXEMPTY)) 97*21145fe5SJordan Rhee if (!(read32(base + UCR1) & UCR1_UARTEN)) 98*21145fe5SJordan Rhee return; 998c4a5a9aSPeng Fan } 1008c4a5a9aSPeng Fan 10126267e82SJerome Forissier static int imx_uart_getchar(struct serial_chip *chip) 1028c4a5a9aSPeng Fan { 10326267e82SJerome Forissier vaddr_t base = chip_to_base(chip); 10426267e82SJerome Forissier 1058c4a5a9aSPeng Fan while (read32(base + UTS) & UTS_RXEMPTY) 1068c4a5a9aSPeng Fan ; 1078c4a5a9aSPeng Fan 1088c4a5a9aSPeng Fan return (read32(base + URXD) & URXD_RX_DATA); 1098c4a5a9aSPeng Fan } 1108c4a5a9aSPeng Fan 11126267e82SJerome Forissier static void imx_uart_putc(struct serial_chip *chip, int ch) 1128c4a5a9aSPeng Fan { 11326267e82SJerome Forissier vaddr_t base = chip_to_base(chip); 1148c4a5a9aSPeng Fan 1154c85b2cfSJordan Rhee /* Wait until there's space in the TX FIFO */ 1164c85b2cfSJordan Rhee while (read32(base + UTS) & UTS_TXFULL) 117*21145fe5SJordan Rhee if (!(read32(base + UCR1) & UCR1_UARTEN)) 118*21145fe5SJordan Rhee return; 1194c85b2cfSJordan Rhee 1204c85b2cfSJordan Rhee write32(ch, base + UTXD); 1218c4a5a9aSPeng Fan } 12226267e82SJerome Forissier 12326267e82SJerome Forissier static const struct serial_ops imx_uart_ops = { 12426267e82SJerome Forissier .flush = imx_uart_flush, 12526267e82SJerome Forissier .getchar = imx_uart_getchar, 12626267e82SJerome Forissier .putc = imx_uart_putc, 12726267e82SJerome Forissier }; 1288d94060aSEtienne Carriere KEEP_PAGER(imx_uart_ops); 12926267e82SJerome Forissier 13026267e82SJerome Forissier void imx_uart_init(struct imx_uart_data *pd, paddr_t base) 13126267e82SJerome Forissier { 13226267e82SJerome Forissier pd->base.pa = base; 13326267e82SJerome Forissier pd->chip.ops = &imx_uart_ops; 13426267e82SJerome Forissier 13526267e82SJerome Forissier /* 13626267e82SJerome Forissier * Do nothing, debug uart(uart0) share with normal world, 13726267e82SJerome Forissier * everything for uart0 initialization is done in bootloader. 13826267e82SJerome Forissier */ 13926267e82SJerome Forissier } 140