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