1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * MediaTek High-speed UART driver 4 * 5 * Copyright (C) 2018 MediaTek Inc. 6 * Author: Weijie Gao <weijie.gao@mediatek.com> 7 */ 8 9 #include <clk.h> 10 #include <common.h> 11 #include <div64.h> 12 #include <dm.h> 13 #include <errno.h> 14 #include <serial.h> 15 #include <watchdog.h> 16 #include <asm/io.h> 17 #include <asm/types.h> 18 19 struct mtk_serial_regs { 20 u32 rbr; 21 u32 ier; 22 u32 fcr; 23 u32 lcr; 24 u32 mcr; 25 u32 lsr; 26 u32 msr; 27 u32 spr; 28 u32 mdr1; 29 u32 highspeed; 30 u32 sample_count; 31 u32 sample_point; 32 u32 fracdiv_l; 33 u32 fracdiv_m; 34 u32 escape_en; 35 u32 guard; 36 u32 rx_sel; 37 }; 38 39 #define thr rbr 40 #define iir fcr 41 #define dll rbr 42 #define dlm ier 43 44 #define UART_LCR_WLS_8 0x03 /* 8 bit character length */ 45 #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ 46 47 #define UART_LSR_DR 0x01 /* Data ready */ 48 #define UART_LSR_THRE 0x20 /* Xmit holding register empty */ 49 50 /* the data is correct if the real baud is within 3%. */ 51 #define BAUD_ALLOW_MAX(baud) ((baud) + (baud) * 3 / 100) 52 #define BAUD_ALLOW_MIX(baud) ((baud) - (baud) * 3 / 100) 53 54 struct mtk_serial_priv { 55 struct mtk_serial_regs __iomem *regs; 56 u32 clock; 57 }; 58 59 static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud) 60 { 61 bool support_clk12m_baud115200; 62 u32 quot, samplecount, realbaud; 63 64 if ((baud <= 115200) && (priv->clock == 12000000)) 65 support_clk12m_baud115200 = true; 66 else 67 support_clk12m_baud115200 = false; 68 69 if (baud <= 115200) { 70 writel(0, &priv->regs->highspeed); 71 quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud); 72 73 if (support_clk12m_baud115200) { 74 writel(3, &priv->regs->highspeed); 75 quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud); 76 if (quot == 0) 77 quot = 1; 78 79 samplecount = DIV_ROUND_CLOSEST(priv->clock, 80 quot * baud); 81 if (samplecount != 0) { 82 realbaud = priv->clock / samplecount / quot; 83 if ((realbaud > BAUD_ALLOW_MAX(baud)) || 84 (realbaud < BAUD_ALLOW_MIX(baud))) { 85 pr_info("baud %d can't be handled\n", 86 baud); 87 } 88 } else { 89 pr_info("samplecount is 0\n"); 90 } 91 } 92 } else if (baud <= 576000) { 93 writel(2, &priv->regs->highspeed); 94 95 /* Set to next lower baudrate supported */ 96 if ((baud == 500000) || (baud == 576000)) 97 baud = 460800; 98 quot = DIV_ROUND_UP(priv->clock, 4 * baud); 99 } else { 100 writel(3, &priv->regs->highspeed); 101 quot = DIV_ROUND_UP(priv->clock, 256 * baud); 102 } 103 104 /* set divisor */ 105 writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr); 106 writel(quot & 0xff, &priv->regs->dll); 107 writel((quot >> 8) & 0xff, &priv->regs->dlm); 108 writel(UART_LCR_WLS_8, &priv->regs->lcr); 109 110 if (baud > 460800) { 111 u32 tmp; 112 113 tmp = DIV_ROUND_CLOSEST(priv->clock, quot * baud); 114 writel(tmp - 1, &priv->regs->sample_count); 115 writel((tmp - 2) >> 1, &priv->regs->sample_point); 116 } else { 117 writel(0, &priv->regs->sample_count); 118 writel(0xff, &priv->regs->sample_point); 119 } 120 121 if (support_clk12m_baud115200) { 122 writel(samplecount - 1, &priv->regs->sample_count); 123 writel((samplecount - 2) >> 1, &priv->regs->sample_point); 124 } 125 } 126 127 static int mtk_serial_setbrg(struct udevice *dev, int baudrate) 128 { 129 struct mtk_serial_priv *priv = dev_get_priv(dev); 130 131 _mtk_serial_setbrg(priv, baudrate); 132 133 return 0; 134 } 135 136 static int mtk_serial_putc(struct udevice *dev, const char ch) 137 { 138 struct mtk_serial_priv *priv = dev_get_priv(dev); 139 140 if (!(readl(&priv->regs->lsr) & UART_LSR_THRE)) 141 return -EAGAIN; 142 143 writel(ch, &priv->regs->thr); 144 145 if (ch == '\n') 146 WATCHDOG_RESET(); 147 148 return 0; 149 } 150 151 static int mtk_serial_getc(struct udevice *dev) 152 { 153 struct mtk_serial_priv *priv = dev_get_priv(dev); 154 155 if (!(readl(&priv->regs->lsr) & UART_LSR_DR)) 156 return -EAGAIN; 157 158 return readl(&priv->regs->rbr); 159 } 160 161 static int mtk_serial_pending(struct udevice *dev, bool input) 162 { 163 struct mtk_serial_priv *priv = dev_get_priv(dev); 164 165 if (input) 166 return (readl(&priv->regs->lsr) & UART_LSR_DR) ? 1 : 0; 167 else 168 return (readl(&priv->regs->lsr) & UART_LSR_THRE) ? 0 : 1; 169 } 170 171 static int mtk_serial_probe(struct udevice *dev) 172 { 173 struct mtk_serial_priv *priv = dev_get_priv(dev); 174 175 /* Disable interrupt */ 176 writel(0, &priv->regs->ier); 177 178 return 0; 179 } 180 181 static int mtk_serial_ofdata_to_platdata(struct udevice *dev) 182 { 183 struct mtk_serial_priv *priv = dev_get_priv(dev); 184 fdt_addr_t addr; 185 struct clk clk; 186 int err; 187 188 addr = dev_read_addr(dev); 189 if (addr == FDT_ADDR_T_NONE) 190 return -EINVAL; 191 192 priv->regs = map_physmem(addr, 0, MAP_NOCACHE); 193 194 err = clk_get_by_index(dev, 0, &clk); 195 if (!err) { 196 err = clk_get_rate(&clk); 197 if (!IS_ERR_VALUE(err)) 198 priv->clock = err; 199 } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) { 200 debug("mtk_serial: failed to get clock\n"); 201 return err; 202 } 203 204 if (!priv->clock) 205 priv->clock = dev_read_u32_default(dev, "clock-frequency", 0); 206 207 if (!priv->clock) { 208 debug("mtk_serial: clock not defined\n"); 209 return -EINVAL; 210 } 211 212 return 0; 213 } 214 215 static const struct dm_serial_ops mtk_serial_ops = { 216 .putc = mtk_serial_putc, 217 .pending = mtk_serial_pending, 218 .getc = mtk_serial_getc, 219 .setbrg = mtk_serial_setbrg, 220 }; 221 222 static const struct udevice_id mtk_serial_ids[] = { 223 { .compatible = "mediatek,hsuart" }, 224 { .compatible = "mediatek,mt6577-uart" }, 225 { } 226 }; 227 228 U_BOOT_DRIVER(serial_mtk) = { 229 .name = "serial_mtk", 230 .id = UCLASS_SERIAL, 231 .of_match = mtk_serial_ids, 232 .ofdata_to_platdata = mtk_serial_ofdata_to_platdata, 233 .priv_auto_alloc_size = sizeof(struct mtk_serial_priv), 234 .probe = mtk_serial_probe, 235 .ops = &mtk_serial_ops, 236 .flags = DM_FLAG_PRE_RELOC, 237 }; 238 239 #ifdef CONFIG_DEBUG_UART_MTK 240 241 #include <debug_uart.h> 242 243 static inline void _debug_uart_init(void) 244 { 245 struct mtk_serial_priv priv; 246 247 priv.regs = (void *) CONFIG_DEBUG_UART_BASE; 248 priv.clock = CONFIG_DEBUG_UART_CLOCK; 249 250 writel(0, &priv.regs->ier); 251 252 _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE); 253 } 254 255 static inline void _debug_uart_putc(int ch) 256 { 257 struct mtk_serial_regs __iomem *regs = 258 (void *) CONFIG_DEBUG_UART_BASE; 259 260 while (!(readl(®s->lsr) & UART_LSR_THRE)) 261 ; 262 263 writel(ch, ®s->thr); 264 } 265 266 DEBUG_UART_FUNCS 267 268 #endif