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 <debug_uart.h> 12 #include <errno.h> 13 #include <serial.h> 14 #include <asm/io.h> 15 #include <asm/types.h> 16 #include <dm/device.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 parity to even */ 145 UART_CTL_RXPAREVEN_MASK | 146 UART_CTL_TXPAREVEN_MASK); 147 148 /* set uart fifo config */ 149 clrsetbits_be32(base + UART_FIFO_CFG_REG, 150 /* clear fifo config */ 151 UART_FIFO_CFG_RX_MASK | 152 UART_FIFO_CFG_TX_MASK, 153 /* set fifo config to 4 */ 154 UART_FIFO_CFG_RX_4 | 155 UART_FIFO_CFG_TX_4); 156 157 /* set baud rate */ 158 val = (clk / baudrate) / 16; 159 if (val & 0x1) 160 val = val; 161 else 162 val = val / 2 - 1; 163 writel_be(val, base + UART_BAUD_REG); 164 165 /* clear interrupts */ 166 writel_be(0, base + UART_IR_REG); 167 168 /* enable uart */ 169 bcm6345_serial_enable(base); 170 171 return 0; 172 } 173 174 static int bcm6345_serial_pending(struct udevice *dev, bool input) 175 { 176 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 177 u32 val = readl_be(priv->base + UART_IR_REG); 178 179 if (input) 180 return !!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY)); 181 else 182 return !(val & UART_IR_STAT(UART_IR_TXEMPTY)); 183 } 184 185 static int bcm6345_serial_setbrg(struct udevice *dev, int baudrate) 186 { 187 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 188 189 return bcm6345_serial_init(priv->base, priv->uartclk, baudrate); 190 } 191 192 static int bcm6345_serial_putc(struct udevice *dev, const char ch) 193 { 194 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 195 u32 val; 196 197 val = readl_be(priv->base + UART_IR_REG); 198 if (!(val & UART_IR_STAT(UART_IR_TXEMPTY))) 199 return -EAGAIN; 200 201 writel_be(ch, priv->base + UART_FIFO_REG); 202 203 return 0; 204 } 205 206 static int bcm6345_serial_getc(struct udevice *dev) 207 { 208 struct bcm6345_serial_priv *priv = dev_get_priv(dev); 209 u32 val; 210 211 val = readl_be(priv->base + UART_IR_REG); 212 if (val & UART_IR_STAT(UART_IR_RXOVER)) 213 setbits_be32(priv->base + UART_CTL_REG, 214 UART_CTL_RSTRXFIFO_MASK); 215 if (!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY))) 216 return -EAGAIN; 217 218 val = readl_be(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 fdt_addr_t addr; 230 fdt_size_t size; 231 int ret; 232 233 /* get address */ 234 addr = dev_get_addr_size_index(dev, 0, &size); 235 if (addr == FDT_ADDR_T_NONE) 236 return -EINVAL; 237 238 priv->base = ioremap(addr, size); 239 240 /* get clock rate */ 241 ret = clk_get_by_index(dev, 0, &clk); 242 if (ret < 0) 243 return ret; 244 priv->uartclk = clk_get_rate(&clk) / 2; 245 clk_free(&clk); 246 247 /* initialize serial */ 248 return bcm6345_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE); 249 } 250 251 static const struct dm_serial_ops bcm6345_serial_ops = { 252 .putc = bcm6345_serial_putc, 253 .pending = bcm6345_serial_pending, 254 .getc = bcm6345_serial_getc, 255 .setbrg = bcm6345_serial_setbrg, 256 }; 257 258 static const struct udevice_id bcm6345_serial_ids[] = { 259 { .compatible = "brcm,bcm6345-uart" }, 260 { /* sentinel */ } 261 }; 262 263 U_BOOT_DRIVER(bcm6345_serial) = { 264 .name = "bcm6345-uart", 265 .id = UCLASS_SERIAL, 266 .of_match = bcm6345_serial_ids, 267 .probe = bcm6345_serial_probe, 268 .priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv), 269 .ops = &bcm6345_serial_ops, 270 .flags = DM_FLAG_PRE_RELOC, 271 }; 272 273 #ifdef CONFIG_DEBUG_UART_BCM6345 274 static inline void _debug_uart_init(void) 275 { 276 void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; 277 278 bcm6345_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); 279 } 280 281 static inline void wait_xfered(void __iomem *base) 282 { 283 do { 284 u32 val = readl_be(base + UART_IR_REG); 285 if (val & UART_IR_STAT(UART_IR_TXEMPTY)) 286 break; 287 } while (1); 288 } 289 290 static inline void _debug_uart_putc(int ch) 291 { 292 void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; 293 294 wait_xfered(base); 295 writel_be(ch, base + UART_FIFO_REG); 296 wait_xfered(base); 297 } 298 299 DEBUG_UART_FUNCS 300 #endif 301