1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2018 Anup Patel <anup@brainfault.org> 4 */ 5 6 #include <clk.h> 7 #include <common.h> 8 #include <debug_uart.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <fdtdec.h> 12 #include <watchdog.h> 13 #include <asm/io.h> 14 #include <linux/compiler.h> 15 #include <serial.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #define UART_TXFIFO_FULL 0x80000000 20 #define UART_RXFIFO_EMPTY 0x80000000 21 #define UART_RXFIFO_DATA 0x000000ff 22 #define UART_TXCTRL_TXEN 0x1 23 #define UART_RXCTRL_RXEN 0x1 24 25 struct uart_sifive { 26 u32 txfifo; 27 u32 rxfifo; 28 u32 txctrl; 29 u32 rxctrl; 30 u32 ie; 31 u32 ip; 32 u32 div; 33 }; 34 35 struct sifive_uart_platdata { 36 unsigned int clock; 37 int saved_input_char; 38 struct uart_sifive *regs; 39 }; 40 41 /* Set up the baud rate in gd struct */ 42 static void _sifive_serial_setbrg(struct uart_sifive *regs, 43 unsigned long clock, unsigned long baud) 44 { 45 writel((u32)((clock / baud) - 1), ®s->div); 46 } 47 48 static void _sifive_serial_init(struct uart_sifive *regs) 49 { 50 writel(UART_TXCTRL_TXEN, ®s->txctrl); 51 writel(UART_RXCTRL_RXEN, ®s->rxctrl); 52 writel(0, ®s->ie); 53 } 54 55 static int _sifive_serial_putc(struct uart_sifive *regs, const char c) 56 { 57 if (readl(®s->txfifo) & UART_TXFIFO_FULL) 58 return -EAGAIN; 59 60 writel(c, ®s->txfifo); 61 62 return 0; 63 } 64 65 static int _sifive_serial_getc(struct uart_sifive *regs) 66 { 67 int ch = readl(®s->rxfifo); 68 69 if (ch & UART_RXFIFO_EMPTY) 70 return -EAGAIN; 71 ch &= UART_RXFIFO_DATA; 72 73 return (!ch) ? -EAGAIN : ch; 74 } 75 76 static int sifive_serial_setbrg(struct udevice *dev, int baudrate) 77 { 78 int err; 79 struct clk clk; 80 struct sifive_uart_platdata *platdata = dev_get_platdata(dev); 81 82 err = clk_get_by_index(dev, 0, &clk); 83 if (!err) { 84 err = clk_get_rate(&clk); 85 if (!IS_ERR_VALUE(err)) 86 platdata->clock = err; 87 } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) { 88 debug("SiFive UART failed to get clock\n"); 89 return err; 90 } 91 92 if (!platdata->clock) 93 platdata->clock = dev_read_u32_default(dev, "clock-frequency", 0); 94 if (!platdata->clock) { 95 debug("SiFive UART clock not defined\n"); 96 return -EINVAL; 97 } 98 99 _sifive_serial_setbrg(platdata->regs, platdata->clock, baudrate); 100 101 return 0; 102 } 103 104 static int sifive_serial_probe(struct udevice *dev) 105 { 106 struct sifive_uart_platdata *platdata = dev_get_platdata(dev); 107 108 /* No need to reinitialize the UART after relocation */ 109 if (gd->flags & GD_FLG_RELOC) 110 return 0; 111 112 platdata->saved_input_char = 0; 113 _sifive_serial_init(platdata->regs); 114 115 return 0; 116 } 117 118 static int sifive_serial_getc(struct udevice *dev) 119 { 120 int c; 121 struct sifive_uart_platdata *platdata = dev_get_platdata(dev); 122 struct uart_sifive *regs = platdata->regs; 123 124 if (platdata->saved_input_char > 0) { 125 c = platdata->saved_input_char; 126 platdata->saved_input_char = 0; 127 return c; 128 } 129 130 while ((c = _sifive_serial_getc(regs)) == -EAGAIN) ; 131 132 return c; 133 } 134 135 static int sifive_serial_putc(struct udevice *dev, const char ch) 136 { 137 int rc; 138 struct sifive_uart_platdata *platdata = dev_get_platdata(dev); 139 140 while ((rc = _sifive_serial_putc(platdata->regs, ch)) == -EAGAIN) ; 141 142 return rc; 143 } 144 145 static int sifive_serial_pending(struct udevice *dev, bool input) 146 { 147 struct sifive_uart_platdata *platdata = dev_get_platdata(dev); 148 struct uart_sifive *regs = platdata->regs; 149 150 if (input) { 151 if (platdata->saved_input_char > 0) 152 return 1; 153 platdata->saved_input_char = _sifive_serial_getc(regs); 154 return (platdata->saved_input_char > 0) ? 1 : 0; 155 } else { 156 return !!(readl(®s->txfifo) & UART_TXFIFO_FULL); 157 } 158 } 159 160 static int sifive_serial_ofdata_to_platdata(struct udevice *dev) 161 { 162 struct sifive_uart_platdata *platdata = dev_get_platdata(dev); 163 164 platdata->regs = (struct uart_sifive *)dev_read_addr(dev); 165 if (IS_ERR(platdata->regs)) 166 return PTR_ERR(platdata->regs); 167 168 return 0; 169 } 170 171 static const struct dm_serial_ops sifive_serial_ops = { 172 .putc = sifive_serial_putc, 173 .getc = sifive_serial_getc, 174 .pending = sifive_serial_pending, 175 .setbrg = sifive_serial_setbrg, 176 }; 177 178 static const struct udevice_id sifive_serial_ids[] = { 179 { .compatible = "sifive,uart0" }, 180 { } 181 }; 182 183 U_BOOT_DRIVER(serial_sifive) = { 184 .name = "serial_sifive", 185 .id = UCLASS_SERIAL, 186 .of_match = sifive_serial_ids, 187 .ofdata_to_platdata = sifive_serial_ofdata_to_platdata, 188 .platdata_auto_alloc_size = sizeof(struct sifive_uart_platdata), 189 .probe = sifive_serial_probe, 190 .ops = &sifive_serial_ops, 191 }; 192 193 #ifdef CONFIG_DEBUG_UART_SIFIVE 194 static inline void _debug_uart_init(void) 195 { 196 struct uart_sifive *regs = 197 (struct uart_sifive *)CONFIG_DEBUG_UART_BASE; 198 199 _sifive_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK, 200 CONFIG_BAUDRATE); 201 _sifive_serial_init(regs); 202 } 203 204 static inline void _debug_uart_putc(int ch) 205 { 206 struct uart_sifive *regs = 207 (struct uart_sifive *)CONFIG_DEBUG_UART_BASE; 208 209 while (_sifive_serial_putc(regs, ch) == -EAGAIN) 210 WATCHDOG_RESET(); 211 } 212 213 DEBUG_UART_FUNCS 214 215 #endif 216