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_be32(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_be32(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_be32(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_be(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_be32(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_be32(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_be(val, base + UART_BAUD_REG); 165 166 /* clear interrupts */ 167 writel_be(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_be(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_be(priv->base + UART_IR_REG); 199 if (!(val & UART_IR_STAT(UART_IR_TXEMPTY))) 200 return -EAGAIN; 201 202 writel_be(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_be(priv->base + UART_IR_REG); 213 if (val & UART_IR_STAT(UART_IR_RXOVER)) 214 setbits_be32(priv->base + UART_CTL_REG, 215 UART_CTL_RSTRXFIFO_MASK); 216 if (!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY))) 217 return -EAGAIN; 218 219 val = readl_be(priv->base + UART_FIFO_REG); 220 if (val & UART_FIFO_ANYERR_MASK) 221 return -EAGAIN; 222 223 return val & UART_FIFO_VALID_MASK; 224 } 225 226 static int bcm6345_serial_probe(struct udevice *dev) 227 { 228 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 229 struct clk clk; 230 int ret; 231 232 /* get address */ 233 priv->base = dev_remap_addr(dev); 234 if (!priv->base) 235 return -EINVAL; 236 237 /* get clock rate */ 238 ret = clk_get_by_index(dev, 0, &clk); 239 if (ret < 0) 240 return ret; 241 priv->uartclk = clk_get_rate(&clk); 242 clk_free(&clk); 243 244 /* initialize serial */ 245 return bcm6345_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE); 246 } 247 248 static const struct dm_serial_ops bcm6345_serial_ops = { 249 .putc = bcm6345_serial_putc, 250 .pending = bcm6345_serial_pending, 251 .getc = bcm6345_serial_getc, 252 .setbrg = bcm6345_serial_setbrg, 253 }; 254 255 static const struct udevice_id bcm6345_serial_ids[] = { 256 { .compatible = "brcm,bcm6345-uart" }, 257 { /* sentinel */ } 258 }; 259 260 U_BOOT_DRIVER(bcm6345_serial) = { 261 .name = "bcm6345-uart", 262 .id = UCLASS_SERIAL, 263 .of_match = bcm6345_serial_ids, 264 .probe = bcm6345_serial_probe, 265 .priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv), 266 .ops = &bcm6345_serial_ops, 267 .flags = DM_FLAG_PRE_RELOC, 268 }; 269 270 #ifdef CONFIG_DEBUG_UART_BCM6345 271 static inline void _debug_uart_init(void) 272 { 273 void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; 274 275 bcm6345_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); 276 } 277 278 static inline void wait_xfered(void __iomem *base) 279 { 280 do { 281 u32 val = readl_be(base + UART_IR_REG); 282 if (val & UART_IR_STAT(UART_IR_TXEMPTY)) 283 break; 284 } while (1); 285 } 286 287 static inline void _debug_uart_putc(int ch) 288 { 289 void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; 290 291 wait_xfered(base); 292 writel_be(ch, base + UART_FIFO_REG); 293 wait_xfered(base); 294 } 295 296 DEBUG_UART_FUNCS 297 #endif 298