1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, Linaro Limited 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include <assert.h> 29 #include <drivers/pl011.h> 30 #include <io.h> 31 #include <keep.h> 32 #include <kernel/dt.h> 33 #include <stdlib.h> 34 #include <trace.h> 35 #include <types_ext.h> 36 #include <util.h> 37 38 #define UART_DR 0x00 /* data register */ 39 #define UART_RSR_ECR 0x04 /* receive status or error clear */ 40 #define UART_DMAWM 0x08 /* DMA watermark configure */ 41 #define UART_TIMEOUT 0x0C /* Timeout period */ 42 /* reserved space */ 43 #define UART_FR 0x18 /* flag register */ 44 #define UART_ILPR 0x20 /* IrDA low-poer */ 45 #define UART_IBRD 0x24 /* integer baud register */ 46 #define UART_FBRD 0x28 /* fractional baud register */ 47 #define UART_LCR_H 0x2C /* line control register */ 48 #define UART_CR 0x30 /* control register */ 49 #define UART_IFLS 0x34 /* interrupt FIFO level select */ 50 #define UART_IMSC 0x38 /* interrupt mask set/clear */ 51 #define UART_RIS 0x3C /* raw interrupt register */ 52 #define UART_MIS 0x40 /* masked interrupt register */ 53 #define UART_ICR 0x44 /* interrupt clear register */ 54 #define UART_DMACR 0x48 /* DMA control register */ 55 56 /* flag register bits */ 57 #define UART_FR_RTXDIS (1 << 13) 58 #define UART_FR_TERI (1 << 12) 59 #define UART_FR_DDCD (1 << 11) 60 #define UART_FR_DDSR (1 << 10) 61 #define UART_FR_DCTS (1 << 9) 62 #define UART_FR_RI (1 << 8) 63 #define UART_FR_TXFE (1 << 7) 64 #define UART_FR_RXFF (1 << 6) 65 #define UART_FR_TXFF (1 << 5) 66 #define UART_FR_RXFE (1 << 4) 67 #define UART_FR_BUSY (1 << 3) 68 #define UART_FR_DCD (1 << 2) 69 #define UART_FR_DSR (1 << 1) 70 #define UART_FR_CTS (1 << 0) 71 72 /* transmit/receive line register bits */ 73 #define UART_LCRH_SPS (1 << 7) 74 #define UART_LCRH_WLEN_8 (3 << 5) 75 #define UART_LCRH_WLEN_7 (2 << 5) 76 #define UART_LCRH_WLEN_6 (1 << 5) 77 #define UART_LCRH_WLEN_5 (0 << 5) 78 #define UART_LCRH_FEN (1 << 4) 79 #define UART_LCRH_STP2 (1 << 3) 80 #define UART_LCRH_EPS (1 << 2) 81 #define UART_LCRH_PEN (1 << 1) 82 #define UART_LCRH_BRK (1 << 0) 83 84 /* control register bits */ 85 #define UART_CR_CTSEN (1 << 15) 86 #define UART_CR_RTSEN (1 << 14) 87 #define UART_CR_OUT2 (1 << 13) 88 #define UART_CR_OUT1 (1 << 12) 89 #define UART_CR_RTS (1 << 11) 90 #define UART_CR_DTR (1 << 10) 91 #define UART_CR_RXE (1 << 9) 92 #define UART_CR_TXE (1 << 8) 93 #define UART_CR_LPE (1 << 7) 94 #define UART_CR_OVSFACT (1 << 3) 95 #define UART_CR_UARTEN (1 << 0) 96 97 #define UART_IMSC_RTIM (1 << 6) 98 #define UART_IMSC_RXIM (1 << 4) 99 100 static vaddr_t chip_to_base(struct serial_chip *chip) 101 { 102 struct pl011_data *pd = 103 container_of(chip, struct pl011_data, chip); 104 105 return io_pa_or_va(&pd->base); 106 } 107 108 static void pl011_flush(struct serial_chip *chip) 109 { 110 vaddr_t base = chip_to_base(chip); 111 112 /* 113 * Wait for the transmit FIFO to be empty. 114 * It can happen that Linux initializes the OP-TEE driver with the 115 * console UART disabled; avoid an infinite loop by checking the UART 116 * enabled flag. Checking it in the loop makes the code safe against 117 * asynchronous disable. 118 */ 119 while ((read32(base + UART_CR) & UART_CR_UARTEN) && 120 !(read32(base + UART_FR) & UART_FR_TXFE)) 121 ; 122 } 123 124 static bool pl011_have_rx_data(struct serial_chip *chip) 125 { 126 vaddr_t base = chip_to_base(chip); 127 128 return !(read32(base + UART_FR) & UART_FR_RXFE); 129 } 130 131 static int pl011_getchar(struct serial_chip *chip) 132 { 133 vaddr_t base = chip_to_base(chip); 134 135 while (!pl011_have_rx_data(chip)) 136 ; 137 return read32(base + UART_DR) & 0xff; 138 } 139 140 static void pl011_putc(struct serial_chip *chip, int ch) 141 { 142 vaddr_t base = chip_to_base(chip); 143 144 /* Wait until there is space in the FIFO or device is disabled */ 145 while (read32(base + UART_FR) & UART_FR_TXFF) 146 ; 147 148 /* Send the character */ 149 write32(ch, base + UART_DR); 150 } 151 152 static const struct serial_ops pl011_ops = { 153 .flush = pl011_flush, 154 .getchar = pl011_getchar, 155 .have_rx_data = pl011_have_rx_data, 156 .putc = pl011_putc, 157 }; 158 KEEP_PAGER(pl011_ops); 159 160 void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk, 161 uint32_t baud_rate) 162 { 163 vaddr_t base; 164 165 pd->base.pa = pbase; 166 pd->chip.ops = &pl011_ops; 167 168 base = io_pa_or_va(&pd->base); 169 170 /* Clear all errors */ 171 write32(0, base + UART_RSR_ECR); 172 /* Disable everything */ 173 write32(0, base + UART_CR); 174 175 if (baud_rate) { 176 uint32_t divisor = (uart_clk * 4) / baud_rate; 177 178 write32(divisor >> 6, base + UART_IBRD); 179 write32(divisor & 0x3f, base + UART_FBRD); 180 } 181 182 /* Configure TX to 8 bits, 1 stop bit, no parity, fifo disabled. */ 183 write32(UART_LCRH_WLEN_8, base + UART_LCR_H); 184 185 /* Enable interrupts for receive and receive timeout */ 186 write32(UART_IMSC_RXIM | UART_IMSC_RTIM, base + UART_IMSC); 187 188 /* Enable UART and RX/TX */ 189 write32(UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE, base + UART_CR); 190 191 pl011_flush(&pd->chip); 192 } 193 194 #ifdef CFG_DT 195 196 static struct serial_chip *pl011_dev_alloc(void) 197 { 198 struct pl011_data *pd = malloc(sizeof(*pd)); 199 200 if (!pd) 201 return NULL; 202 return &pd->chip; 203 } 204 205 static int pl011_dev_init(struct serial_chip *chip, const void *fdt, int offs, 206 const char *parms) 207 { 208 struct pl011_data *pd = container_of(chip, struct pl011_data, chip); 209 vaddr_t vbase; 210 paddr_t pbase; 211 size_t size; 212 213 if (parms && parms[0]) 214 IMSG("pl011: device parameters ignored (%s)", parms); 215 216 if (dt_map_dev(fdt, offs, &vbase, &size) < 0) 217 return -1; 218 219 if (size != 0x1000) { 220 EMSG("pl011: unexpected register size: %zx", size); 221 return -1; 222 } 223 224 pbase = virt_to_phys((void *)vbase); 225 pl011_init(pd, pbase, 0, 0); 226 227 return 0; 228 } 229 230 static void pl011_dev_free(struct serial_chip *chip) 231 { 232 struct pl011_data *pd = container_of(chip, struct pl011_data, chip); 233 234 free(pd); 235 } 236 237 static const struct serial_driver pl011_driver = { 238 .dev_alloc = pl011_dev_alloc, 239 .dev_init = pl011_dev_init, 240 .dev_free = pl011_dev_free, 241 }; 242 243 static const struct dt_device_match pl011_match_table[] = { 244 { .compatible = "arm,pl011" }, 245 { 0 } 246 }; 247 248 const struct dt_driver pl011_dt_driver __dt_driver = { 249 .name = "pl011", 250 .match_table = pl011_match_table, 251 .driver = &pl011_driver, 252 }; 253 254 #endif /* CFG_DT */ 255