1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com> 4 * 5 * Derived from linux/drivers/tty/serial/bcm63xx_uart.c: 6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 7 */ 8 9 #include <clk.h> 10 #include <dm.h> 11 #include <debug_uart.h> 12 #include <errno.h> 13 #include <serial.h> 14 #include <asm/io.h> 15 #include <asm/types.h> 16 17 /* UART Control register */ 18 #define UART_CTL_REG 0x0 19 #define UART_CTL_RXTIMEOUT_MASK 0x1f 20 #define UART_CTL_RXTIMEOUT_5 0x5 21 #define UART_CTL_RSTRXFIFO_SHIFT 6 22 #define UART_CTL_RSTRXFIFO_MASK (1 << UART_CTL_RSTRXFIFO_SHIFT) 23 #define UART_CTL_RSTTXFIFO_SHIFT 7 24 #define UART_CTL_RSTTXFIFO_MASK (1 << UART_CTL_RSTTXFIFO_SHIFT) 25 #define UART_CTL_STOPBITS_SHIFT 8 26 #define UART_CTL_STOPBITS_MASK (0xf << UART_CTL_STOPBITS_SHIFT) 27 #define UART_CTL_STOPBITS_1 (0x7 << UART_CTL_STOPBITS_SHIFT) 28 #define UART_CTL_BITSPERSYM_SHIFT 12 29 #define UART_CTL_BITSPERSYM_MASK (0x3 << UART_CTL_BITSPERSYM_SHIFT) 30 #define UART_CTL_BITSPERSYM_8 (0x3 << UART_CTL_BITSPERSYM_SHIFT) 31 #define UART_CTL_XMITBRK_SHIFT 14 32 #define UART_CTL_XMITBRK_MASK (1 << UART_CTL_XMITBRK_SHIFT) 33 #define UART_CTL_RSVD_SHIFT 15 34 #define UART_CTL_RSVD_MASK (1 << UART_CTL_RSVD_SHIFT) 35 #define UART_CTL_RXPAREVEN_SHIFT 16 36 #define UART_CTL_RXPAREVEN_MASK (1 << UART_CTL_RXPAREVEN_SHIFT) 37 #define UART_CTL_RXPAREN_SHIFT 17 38 #define UART_CTL_RXPAREN_MASK (1 << UART_CTL_RXPAREN_SHIFT) 39 #define UART_CTL_TXPAREVEN_SHIFT 18 40 #define UART_CTL_TXPAREVEN_MASK (1 << UART_CTL_TXPAREVEN_SHIFT) 41 #define UART_CTL_TXPAREN_SHIFT 19 42 #define UART_CTL_TXPAREN_MASK (1 << UART_CTL_TXPAREN_SHIFT) 43 #define UART_CTL_LOOPBACK_SHIFT 20 44 #define UART_CTL_LOOPBACK_MASK (1 << UART_CTL_LOOPBACK_SHIFT) 45 #define UART_CTL_RXEN_SHIFT 21 46 #define UART_CTL_RXEN_MASK (1 << UART_CTL_RXEN_SHIFT) 47 #define UART_CTL_TXEN_SHIFT 22 48 #define UART_CTL_TXEN_MASK (1 << UART_CTL_TXEN_SHIFT) 49 #define UART_CTL_BRGEN_SHIFT 23 50 #define UART_CTL_BRGEN_MASK (1 << UART_CTL_BRGEN_SHIFT) 51 52 /* UART Baudword register */ 53 #define UART_BAUD_REG 0x4 54 55 /* UART FIFO Config register */ 56 #define UART_FIFO_CFG_REG 0x8 57 #define UART_FIFO_CFG_RX_SHIFT 8 58 #define UART_FIFO_CFG_RX_MASK (0xf << UART_FIFO_CFG_RX_SHIFT) 59 #define UART_FIFO_CFG_RX_4 (0x4 << UART_FIFO_CFG_RX_SHIFT) 60 #define UART_FIFO_CFG_TX_SHIFT 12 61 #define UART_FIFO_CFG_TX_MASK (0xf << UART_FIFO_CFG_TX_SHIFT) 62 #define UART_FIFO_CFG_TX_4 (0x4 << UART_FIFO_CFG_TX_SHIFT) 63 64 /* UART Interrupt register */ 65 #define UART_IR_REG 0x10 66 #define UART_IR_STAT(x) (1 << (x)) 67 #define UART_IR_TXEMPTY 5 68 #define UART_IR_RXOVER 7 69 #define UART_IR_RXNOTEMPTY 11 70 71 /* UART FIFO register */ 72 #define UART_FIFO_REG 0x14 73 #define UART_FIFO_VALID_MASK 0xff 74 #define UART_FIFO_FRAMEERR_SHIFT 8 75 #define UART_FIFO_FRAMEERR_MASK (1 << UART_FIFO_FRAMEERR_SHIFT) 76 #define UART_FIFO_PARERR_SHIFT 9 77 #define UART_FIFO_PARERR_MASK (1 << UART_FIFO_PARERR_SHIFT) 78 #define UART_FIFO_BRKDET_SHIFT 10 79 #define UART_FIFO_BRKDET_MASK (1 << UART_FIFO_BRKDET_SHIFT) 80 #define UART_FIFO_ANYERR_MASK (UART_FIFO_FRAMEERR_MASK | \ 81 UART_FIFO_PARERR_MASK | \ 82 UART_FIFO_BRKDET_MASK) 83 84 struct bcm6345_serial_priv { 85 void __iomem *base; 86 ulong uartclk; 87 }; 88 89 /* enable rx & tx operation on uart */ 90 static void bcm6345_serial_enable(void __iomem *base) 91 { 92 setbits_32(base + UART_CTL_REG, UART_CTL_BRGEN_MASK | 93 UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK); 94 } 95 96 /* disable rx & tx operation on uart */ 97 static void bcm6345_serial_disable(void __iomem *base) 98 { 99 clrbits_32(base + UART_CTL_REG, UART_CTL_BRGEN_MASK | 100 UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK); 101 } 102 103 /* clear all unread data in rx fifo and unsent data in tx fifo */ 104 static void bcm6345_serial_flush(void __iomem *base) 105 { 106 /* empty rx and tx fifo */ 107 setbits_32(base + UART_CTL_REG, UART_CTL_RSTRXFIFO_MASK | 108 UART_CTL_RSTTXFIFO_MASK); 109 110 /* read any pending char to make sure all irq status are cleared */ 111 readl(base + UART_FIFO_REG); 112 } 113 114 static int bcm6345_serial_init(void __iomem *base, ulong clk, u32 baudrate) 115 { 116 u32 val; 117 118 /* mask all irq and flush port */ 119 bcm6345_serial_disable(base); 120 bcm6345_serial_flush(base); 121 122 /* set uart control config */ 123 clrsetbits_32(base + UART_CTL_REG, 124 /* clear rx timeout */ 125 UART_CTL_RXTIMEOUT_MASK | 126 /* clear stop bits */ 127 UART_CTL_STOPBITS_MASK | 128 /* clear bits per symbol */ 129 UART_CTL_BITSPERSYM_MASK | 130 /* clear xmit break */ 131 UART_CTL_XMITBRK_MASK | 132 /* clear reserved bit */ 133 UART_CTL_RSVD_MASK | 134 /* disable parity */ 135 UART_CTL_RXPAREN_MASK | 136 UART_CTL_TXPAREN_MASK | 137 /* disable loopback */ 138 UART_CTL_LOOPBACK_MASK, 139 /* set timeout to 5 */ 140 UART_CTL_RXTIMEOUT_5 | 141 /* set 8 bits/symbol */ 142 UART_CTL_BITSPERSYM_8 | 143 /* set 1 stop bit */ 144 UART_CTL_STOPBITS_1 | 145 /* set parity to even */ 146 UART_CTL_RXPAREVEN_MASK | 147 UART_CTL_TXPAREVEN_MASK); 148 149 /* set uart fifo config */ 150 clrsetbits_32(base + UART_FIFO_CFG_REG, 151 /* clear fifo config */ 152 UART_FIFO_CFG_RX_MASK | 153 UART_FIFO_CFG_TX_MASK, 154 /* set fifo config to 4 */ 155 UART_FIFO_CFG_RX_4 | 156 UART_FIFO_CFG_TX_4); 157 158 /* set baud rate */ 159 val = ((clk / baudrate) >> 4); 160 if (val & 0x1) 161 val = (val >> 1); 162 else 163 val = (val >> 1) - 1; 164 writel(val, base + UART_BAUD_REG); 165 166 /* clear interrupts */ 167 writel(0, base + UART_IR_REG); 168 169 /* enable uart */ 170 bcm6345_serial_enable(base); 171 172 return 0; 173 } 174 175 static int bcm6345_serial_pending(struct udevice *dev, bool input) 176 { 177 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 178 u32 val = readl(priv->base + UART_IR_REG); 179 180 if (input) 181 return !!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY)); 182 else 183 return !(val & UART_IR_STAT(UART_IR_TXEMPTY)); 184 } 185 186 static int bcm6345_serial_setbrg(struct udevice *dev, int baudrate) 187 { 188 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 189 190 return bcm6345_serial_init(priv->base, priv->uartclk, baudrate); 191 } 192 193 static int bcm6345_serial_putc(struct udevice *dev, const char ch) 194 { 195 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 196 u32 val; 197 198 val = readl(priv->base + UART_IR_REG); 199 if (!(val & UART_IR_STAT(UART_IR_TXEMPTY))) 200 return -EAGAIN; 201 202 writel(ch, priv->base + UART_FIFO_REG); 203 204 return 0; 205 } 206 207 static int bcm6345_serial_getc(struct udevice *dev) 208 { 209 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 210 u32 val; 211 212 val = readl(priv->base + UART_IR_REG); 213 if (val & UART_IR_STAT(UART_IR_RXOVER)) 214 setbits_32(priv->base + UART_CTL_REG, UART_CTL_RSTRXFIFO_MASK); 215 if (!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY))) 216 return -EAGAIN; 217 218 val = readl(priv->base + UART_FIFO_REG); 219 if (val & UART_FIFO_ANYERR_MASK) 220 return -EAGAIN; 221 222 return val & UART_FIFO_VALID_MASK; 223 } 224 225 static int bcm6345_serial_probe(struct udevice *dev) 226 { 227 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 228 struct clk clk; 229 int ret; 230 231 /* get address */ 232 priv->base = dev_remap_addr(dev); 233 if (!priv->base) 234 return -EINVAL; 235 236 /* get clock rate */ 237 ret = clk_get_by_index(dev, 0, &clk); 238 if (ret < 0) 239 return ret; 240 priv->uartclk = clk_get_rate(&clk); 241 clk_free(&clk); 242 243 /* initialize serial */ 244 return bcm6345_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE); 245 } 246 247 static const struct dm_serial_ops bcm6345_serial_ops = { 248 .putc = bcm6345_serial_putc, 249 .pending = bcm6345_serial_pending, 250 .getc = bcm6345_serial_getc, 251 .setbrg = bcm6345_serial_setbrg, 252 }; 253 254 static const struct udevice_id bcm6345_serial_ids[] = { 255 { .compatible = "brcm,bcm6345-uart" }, 256 { /* sentinel */ } 257 }; 258 259 U_BOOT_DRIVER(bcm6345_serial) = { 260 .name = "bcm6345-uart", 261 .id = UCLASS_SERIAL, 262 .of_match = bcm6345_serial_ids, 263 .probe = bcm6345_serial_probe, 264 .priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv), 265 .ops = &bcm6345_serial_ops, 266 }; 267 268 #ifdef CONFIG_DEBUG_UART_BCM6345 269 static inline void _debug_uart_init(void) 270 { 271 void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; 272 273 bcm6345_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); 274 } 275 276 static inline void wait_xfered(void __iomem *base) 277 { 278 do { 279 u32 val = readl(base + UART_IR_REG); 280 if (val & UART_IR_STAT(UART_IR_TXEMPTY)) 281 break; 282 } while (1); 283 } 284 285 static inline void _debug_uart_putc(int ch) 286 { 287 void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; 288 289 wait_xfered(base); 290 writel(ch, base + UART_FIFO_REG); 291 wait_xfered(base); 292 } 293 294 DEBUG_UART_FUNCS 295 #endif 296