1 /* 2 * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <div64.h> 10 #include <errno.h> 11 #include <serial.h> 12 #include <asm/io.h> 13 #include <asm/addrspace.h> 14 #include <asm/types.h> 15 #include <dm/pinctrl.h> 16 #include <mach/ar71xx_regs.h> 17 18 #define AR933X_UART_DATA_REG 0x00 19 #define AR933X_UART_CS_REG 0x04 20 #define AR933X_UART_CLK_REG 0x08 21 22 #define AR933X_UART_DATA_TX_RX_MASK 0xff 23 #define AR933X_UART_DATA_RX_CSR BIT(8) 24 #define AR933X_UART_DATA_TX_CSR BIT(9) 25 #define AR933X_UART_CS_IF_MODE_S 2 26 #define AR933X_UART_CS_IF_MODE_M 0x3 27 #define AR933X_UART_CS_IF_MODE_DTE 1 28 #define AR933X_UART_CS_IF_MODE_DCE 2 29 #define AR933X_UART_CS_TX_RDY_ORIDE BIT(7) 30 #define AR933X_UART_CS_RX_RDY_ORIDE BIT(8) 31 #define AR933X_UART_CLK_STEP_M 0xffff 32 #define AR933X_UART_CLK_SCALE_M 0xfff 33 #define AR933X_UART_CLK_SCALE_S 16 34 #define AR933X_UART_CLK_STEP_S 0 35 36 struct ar933x_serial_priv { 37 void __iomem *regs; 38 }; 39 40 /* 41 * Baudrate algorithm come from Linux/drivers/tty/serial/ar933x_uart.c 42 * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17)) 43 */ 44 static u32 ar933x_serial_get_baud(u32 clk, u32 scale, u32 step) 45 { 46 u64 t; 47 u32 div; 48 49 div = (2 << 16) * (scale + 1); 50 t = clk; 51 t *= step; 52 t += (div / 2); 53 do_div(t, div); 54 55 return t; 56 } 57 58 static void ar933x_serial_get_scale_step(u32 clk, u32 baud, 59 u32 *scale, u32 *step) 60 { 61 u32 tscale, baudrate; 62 long min_diff; 63 64 *scale = 0; 65 *step = 0; 66 67 min_diff = baud; 68 for (tscale = 0; tscale < AR933X_UART_CLK_SCALE_M; tscale++) { 69 u64 tstep; 70 int diff; 71 72 tstep = baud * (tscale + 1); 73 tstep *= (2 << 16); 74 do_div(tstep, clk); 75 76 if (tstep > AR933X_UART_CLK_STEP_M) 77 break; 78 79 baudrate = ar933x_serial_get_baud(clk, tscale, tstep); 80 diff = abs(baudrate - baud); 81 if (diff < min_diff) { 82 min_diff = diff; 83 *scale = tscale; 84 *step = tstep; 85 } 86 } 87 } 88 89 static int ar933x_serial_setbrg(struct udevice *dev, int baudrate) 90 { 91 struct ar933x_serial_priv *priv = dev_get_priv(dev); 92 u32 val, scale, step; 93 94 val = get_serial_clock(); 95 ar933x_serial_get_scale_step(val, baudrate, &scale, &step); 96 97 val = (scale & AR933X_UART_CLK_SCALE_M) 98 << AR933X_UART_CLK_SCALE_S; 99 val |= (step & AR933X_UART_CLK_STEP_M) 100 << AR933X_UART_CLK_STEP_S; 101 writel(val, priv->regs + AR933X_UART_CLK_REG); 102 103 return 0; 104 } 105 106 static int ar933x_serial_putc(struct udevice *dev, const char c) 107 { 108 struct ar933x_serial_priv *priv = dev_get_priv(dev); 109 u32 data; 110 111 data = readl(priv->regs + AR933X_UART_DATA_REG); 112 if (!(data & AR933X_UART_DATA_TX_CSR)) 113 return -EAGAIN; 114 115 data = (u32)c | AR933X_UART_DATA_TX_CSR; 116 writel(data, priv->regs + AR933X_UART_DATA_REG); 117 118 return 0; 119 } 120 121 static int ar933x_serial_getc(struct udevice *dev) 122 { 123 struct ar933x_serial_priv *priv = dev_get_priv(dev); 124 u32 data; 125 126 data = readl(priv->regs + AR933X_UART_DATA_REG); 127 if (!(data & AR933X_UART_DATA_RX_CSR)) 128 return -EAGAIN; 129 130 writel(AR933X_UART_DATA_RX_CSR, priv->regs + AR933X_UART_DATA_REG); 131 return data & AR933X_UART_DATA_TX_RX_MASK; 132 } 133 134 static int ar933x_serial_pending(struct udevice *dev, bool input) 135 { 136 struct ar933x_serial_priv *priv = dev_get_priv(dev); 137 u32 data; 138 139 data = readl(priv->regs + AR933X_UART_DATA_REG); 140 if (input) 141 return (data & AR933X_UART_DATA_RX_CSR) ? 1 : 0; 142 else 143 return (data & AR933X_UART_DATA_TX_CSR) ? 0 : 1; 144 } 145 146 static int ar933x_serial_probe(struct udevice *dev) 147 { 148 struct ar933x_serial_priv *priv = dev_get_priv(dev); 149 fdt_addr_t addr; 150 u32 val; 151 152 addr = devfdt_get_addr(dev); 153 if (addr == FDT_ADDR_T_NONE) 154 return -EINVAL; 155 156 priv->regs = map_physmem(addr, AR933X_UART_SIZE, 157 MAP_NOCACHE); 158 159 /* 160 * UART controller configuration: 161 * - no DMA 162 * - no interrupt 163 * - DCE mode 164 * - no flow control 165 * - set RX ready oride 166 * - set TX ready oride 167 */ 168 val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) | 169 AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE; 170 writel(val, priv->regs + AR933X_UART_CS_REG); 171 return 0; 172 } 173 174 static const struct dm_serial_ops ar933x_serial_ops = { 175 .putc = ar933x_serial_putc, 176 .pending = ar933x_serial_pending, 177 .getc = ar933x_serial_getc, 178 .setbrg = ar933x_serial_setbrg, 179 }; 180 181 static const struct udevice_id ar933x_serial_ids[] = { 182 { .compatible = "qca,ar9330-uart" }, 183 { } 184 }; 185 186 U_BOOT_DRIVER(serial_ar933x) = { 187 .name = "serial_ar933x", 188 .id = UCLASS_SERIAL, 189 .of_match = ar933x_serial_ids, 190 .priv_auto_alloc_size = sizeof(struct ar933x_serial_priv), 191 .probe = ar933x_serial_probe, 192 .ops = &ar933x_serial_ops, 193 .flags = DM_FLAG_PRE_RELOC, 194 }; 195 196 #ifdef CONFIG_DEBUG_UART_AR933X 197 198 #include <debug_uart.h> 199 200 static inline void _debug_uart_init(void) 201 { 202 void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE; 203 u32 val, scale, step; 204 205 /* 206 * UART controller configuration: 207 * - no DMA 208 * - no interrupt 209 * - DCE mode 210 * - no flow control 211 * - set RX ready oride 212 * - set TX ready oride 213 */ 214 val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) | 215 AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE; 216 writel(val, regs + AR933X_UART_CS_REG); 217 218 ar933x_serial_get_scale_step(CONFIG_DEBUG_UART_CLOCK, 219 CONFIG_BAUDRATE, &scale, &step); 220 221 val = (scale & AR933X_UART_CLK_SCALE_M) 222 << AR933X_UART_CLK_SCALE_S; 223 val |= (step & AR933X_UART_CLK_STEP_M) 224 << AR933X_UART_CLK_STEP_S; 225 writel(val, regs + AR933X_UART_CLK_REG); 226 } 227 228 static inline void _debug_uart_putc(int c) 229 { 230 void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE; 231 u32 data; 232 233 do { 234 data = readl(regs + AR933X_UART_DATA_REG); 235 } while (!(data & AR933X_UART_DATA_TX_CSR)); 236 237 data = (u32)c | AR933X_UART_DATA_TX_CSR; 238 writel(data, regs + AR933X_UART_DATA_REG); 239 } 240 241 DEBUG_UART_FUNCS 242 243 #endif 244