1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2015 Freescale Semiconductor, Inc. 4 * All rights reserved. 5 * Copyright 2018-2019 NXP. 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 30 #include <assert.h> 31 #include <drivers/imx_uart.h> 32 #include <io.h> 33 #include <keep.h> 34 #include <kernel/dt.h> 35 #include <kernel/dt_driver.h> 36 #include <util.h> 37 38 /* Register definitions */ 39 #define URXD 0x0 /* Receiver Register */ 40 #define UTXD 0x40 /* Transmitter Register */ 41 #define UCR1 0x80 /* Control Register 1 */ 42 #define UCR2 0x84 /* Control Register 2 */ 43 #define UCR3 0x88 /* Control Register 3 */ 44 #define UCR4 0x8c /* Control Register 4 */ 45 #define UFCR 0x90 /* FIFO Control Register */ 46 #define USR1 0x94 /* Status Register 1 */ 47 #define USR2 0x98 /* Status Register 2 */ 48 #define UESC 0x9c /* Escape Character Register */ 49 #define UTIM 0xa0 /* Escape Timer Register */ 50 #define UBIR 0xa4 /* BRM Incremental Register */ 51 #define UBMR 0xa8 /* BRM Modulator Register */ 52 #define UBRC 0xac /* Baud Rate Count Register */ 53 #define UTS 0xb4 /* UART Test Register (mx31) */ 54 #define USIZE 0xb8 /* UTS + sizeof(uint32_t) */ 55 56 /* UART Control Register Bit Fields.*/ 57 #define URXD_CHARRDY (1<<15) 58 #define URXD_ERR (1<<14) 59 #define URXD_OVRRUN (1<<13) 60 #define URXD_FRMERR (1<<12) 61 #define URXD_BRK (1<<11) 62 #define URXD_PRERR (1<<10) 63 #define URXD_RX_DATA (0xFF) 64 #define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ 65 #define UCR1_ADBR (1<<14) /* Auto detect baud rate */ 66 #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ 67 #define UCR1_IDEN (1<<12) /* Idle condition interrupt */ 68 #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ 69 #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ 70 #define UCR1_IREN (1<<7) /* Infrared interface enable */ 71 #define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ 72 #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ 73 #define UCR1_SNDBRK (1<<4) /* Send break */ 74 #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ 75 #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ 76 #define UCR1_DOZE (1<<1) /* Doze */ 77 #define UCR1_UARTEN (1<<0) /* UART enabled */ 78 79 #define UTS_FRCPERR (1<<13) /* Force parity error */ 80 #define UTS_LOOP (1<<12) /* Loop tx and rx */ 81 #define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ 82 #define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ 83 #define UTS_TXFULL (1<<4) /* TxFIFO full */ 84 #define UTS_RXFULL (1<<3) /* RxFIFO full */ 85 #define UTS_SOFTRST (1<<0) /* Software reset */ 86 87 static vaddr_t chip_to_base(struct serial_chip *chip) 88 { 89 struct imx_uart_data *pd = 90 container_of(chip, struct imx_uart_data, chip); 91 92 return io_pa_or_va(&pd->base, USIZE); 93 } 94 95 static void imx_uart_flush(struct serial_chip *chip) 96 { 97 vaddr_t base = chip_to_base(chip); 98 99 100 while (!(io_read32(base + UTS) & UTS_TXEMPTY)) 101 if (!(io_read32(base + UCR1) & UCR1_UARTEN)) 102 return; 103 } 104 105 static int imx_uart_getchar(struct serial_chip *chip) 106 { 107 vaddr_t base = chip_to_base(chip); 108 109 while (io_read32(base + UTS) & UTS_RXEMPTY) 110 ; 111 112 return (io_read32(base + URXD) & URXD_RX_DATA); 113 } 114 115 static void imx_uart_putc(struct serial_chip *chip, int ch) 116 { 117 vaddr_t base = chip_to_base(chip); 118 119 /* Wait until there's space in the TX FIFO */ 120 while (io_read32(base + UTS) & UTS_TXFULL) 121 if (!(io_read32(base + UCR1) & UCR1_UARTEN)) 122 return; 123 124 io_write32(base + UTXD, ch); 125 } 126 127 static const struct serial_ops imx_uart_ops = { 128 .flush = imx_uart_flush, 129 .getchar = imx_uart_getchar, 130 .putc = imx_uart_putc, 131 }; 132 DECLARE_KEEP_PAGER(imx_uart_ops); 133 134 void imx_uart_init(struct imx_uart_data *pd, paddr_t base) 135 { 136 pd->base.pa = base; 137 pd->chip.ops = &imx_uart_ops; 138 139 /* 140 * Do nothing, debug uart(uart0) share with normal world, 141 * everything for uart0 initialization is done in bootloader. 142 */ 143 } 144 145 #ifdef CFG_DT 146 static struct serial_chip *imx_uart_dev_alloc(void) 147 { 148 struct imx_uart_data *pd = calloc(1, sizeof(*pd)); 149 150 if (!pd) 151 return NULL; 152 153 return &pd->chip; 154 } 155 156 static int imx_uart_dev_init(struct serial_chip *chip, const void *fdt, 157 int offs, const char *parms) 158 { 159 struct imx_uart_data *pd = 160 container_of(chip, struct imx_uart_data, chip); 161 vaddr_t vbase = 0; 162 paddr_t pbase = 0; 163 size_t size = 0; 164 165 if (parms && parms[0]) 166 IMSG("imx_uart: device parameters ignored (%s)", parms); 167 168 if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) 169 return -1; 170 171 pbase = virt_to_phys((void *)vbase); 172 imx_uart_init(pd, pbase); 173 174 return 0; 175 } 176 177 static void imx_uart_dev_free(struct serial_chip *chip) 178 { 179 struct imx_uart_data *pd = 180 container_of(chip, struct imx_uart_data, chip); 181 182 free(pd); 183 } 184 185 static const struct serial_driver imx_uart_driver = { 186 .dev_alloc = imx_uart_dev_alloc, 187 .dev_init = imx_uart_dev_init, 188 .dev_free = imx_uart_dev_free, 189 }; 190 191 static const struct dt_device_match imx_match_table[] = { 192 { .compatible = "fsl,imx6q-uart" }, 193 { 0 } 194 }; 195 196 DEFINE_DT_DRIVER(imx_dt_driver) = { 197 .name = "imx_uart", 198 .type = DT_DRIVER_UART, 199 .match_table = imx_match_table, 200 .driver = &imx_uart_driver, 201 }; 202 203 #endif /* CFG_DT */ 204