1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* Synopsys DesignWare 8250 library. */ |
3 | |
4 | #include <linux/bitops.h> |
5 | #include <linux/bitfield.h> |
6 | #include <linux/delay.h> |
7 | #include <linux/device.h> |
8 | #include <linux/kernel.h> |
9 | #include <linux/math.h> |
10 | #include <linux/property.h> |
11 | #include <linux/serial_8250.h> |
12 | #include <linux/serial_core.h> |
13 | |
14 | #include "8250_dwlib.h" |
15 | |
16 | /* Offsets for the DesignWare specific registers */ |
17 | #define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */ |
18 | #define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */ |
19 | #define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */ |
20 | #define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ |
21 | #define DW_UART_RAR 0xc4 /* Receive Address Register */ |
22 | #define DW_UART_TAR 0xc8 /* Transmit Address Register */ |
23 | #define DW_UART_LCR_EXT 0xcc /* Line Extended Control Register */ |
24 | #define DW_UART_CPR 0xf4 /* Component Parameter Register */ |
25 | #define DW_UART_UCV 0xf8 /* UART Component Version */ |
26 | |
27 | /* Receive / Transmit Address Register bits */ |
28 | #define DW_UART_ADDR_MASK GENMASK(7, 0) |
29 | |
30 | /* Line Status Register bits */ |
31 | #define DW_UART_LSR_ADDR_RCVD BIT(8) |
32 | |
33 | /* Transceiver Control Register bits */ |
34 | #define DW_UART_TCR_RS485_EN BIT(0) |
35 | #define DW_UART_TCR_RE_POL BIT(1) |
36 | #define DW_UART_TCR_DE_POL BIT(2) |
37 | #define DW_UART_TCR_XFER_MODE GENMASK(4, 3) |
38 | #define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0) |
39 | #define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1) |
40 | #define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2) |
41 | |
42 | /* Line Extended Control Register bits */ |
43 | #define DW_UART_LCR_EXT_DLS_E BIT(0) |
44 | #define DW_UART_LCR_EXT_ADDR_MATCH BIT(1) |
45 | #define DW_UART_LCR_EXT_SEND_ADDR BIT(2) |
46 | #define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3) |
47 | |
48 | /* Component Parameter Register bits */ |
49 | #define DW_UART_CPR_ABP_DATA_WIDTH GENMASK(1, 0) |
50 | #define DW_UART_CPR_AFCE_MODE BIT(4) |
51 | #define DW_UART_CPR_THRE_MODE BIT(5) |
52 | #define DW_UART_CPR_SIR_MODE BIT(6) |
53 | #define DW_UART_CPR_SIR_LP_MODE BIT(7) |
54 | #define DW_UART_CPR_ADDITIONAL_FEATURES BIT(8) |
55 | #define DW_UART_CPR_FIFO_ACCESS BIT(9) |
56 | #define DW_UART_CPR_FIFO_STAT BIT(10) |
57 | #define DW_UART_CPR_SHADOW BIT(11) |
58 | #define DW_UART_CPR_ENCODED_PARMS BIT(12) |
59 | #define BIT(13) |
60 | #define DW_UART_CPR_FIFO_MODE GENMASK(23, 16) |
61 | |
62 | /* Helper for FIFO size calculation */ |
63 | #define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16) |
64 | |
65 | /* |
66 | * divisor = div(I) + div(F) |
67 | * "I" means integer, "F" means fractional |
68 | * quot = div(I) = clk / (16 * baud) |
69 | * frac = div(F) * 2^dlf_size |
70 | * |
71 | * let rem = clk % (16 * baud) |
72 | * we have: div(F) * (16 * baud) = rem |
73 | * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud) |
74 | */ |
75 | static unsigned int dw8250_get_divisor(struct uart_port *p, unsigned int baud, |
76 | unsigned int *frac) |
77 | { |
78 | unsigned int quot, rem, base_baud = baud * 16; |
79 | struct dw8250_port_data *d = p->private_data; |
80 | |
81 | quot = p->uartclk / base_baud; |
82 | rem = p->uartclk % base_baud; |
83 | *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud); |
84 | |
85 | return quot; |
86 | } |
87 | |
88 | static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, |
89 | unsigned int quot, unsigned int quot_frac) |
90 | { |
91 | dw8250_writel_ext(p, DW_UART_DLF, reg: quot_frac); |
92 | serial8250_do_set_divisor(port: p, baud, quot, quot_frac); |
93 | } |
94 | |
95 | void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, |
96 | const struct ktermios *old) |
97 | { |
98 | p->status &= ~UPSTAT_AUTOCTS; |
99 | if (termios->c_cflag & CRTSCTS) |
100 | p->status |= UPSTAT_AUTOCTS; |
101 | |
102 | serial8250_do_set_termios(port: p, termios, old); |
103 | |
104 | /* Filter addresses which have 9th bit set */ |
105 | p->ignore_status_mask |= DW_UART_LSR_ADDR_RCVD; |
106 | p->read_status_mask |= DW_UART_LSR_ADDR_RCVD; |
107 | } |
108 | EXPORT_SYMBOL_GPL(dw8250_do_set_termios); |
109 | |
110 | /* |
111 | * Wait until re is de-asserted for sure. An ongoing receive will keep |
112 | * re asserted until end of frame. Without BUSY indication available, |
113 | * only available course of action is to wait for the time it takes to |
114 | * receive one frame (there might nothing to receive but w/o BUSY the |
115 | * driver cannot know). |
116 | */ |
117 | static void dw8250_wait_re_deassert(struct uart_port *p) |
118 | { |
119 | ndelay(p->frame_time); |
120 | } |
121 | |
122 | static void dw8250_update_rar(struct uart_port *p, u32 addr) |
123 | { |
124 | u32 re_en = dw8250_readl_ext(p, DW_UART_RE_EN); |
125 | |
126 | /* |
127 | * RAR shouldn't be changed while receiving. Thus, de-assert RE_EN |
128 | * if asserted and wait. |
129 | */ |
130 | if (re_en) |
131 | dw8250_writel_ext(p, DW_UART_RE_EN, reg: 0); |
132 | dw8250_wait_re_deassert(p); |
133 | dw8250_writel_ext(p, DW_UART_RAR, reg: addr); |
134 | if (re_en) |
135 | dw8250_writel_ext(p, DW_UART_RE_EN, reg: re_en); |
136 | } |
137 | |
138 | static void dw8250_rs485_set_addr(struct uart_port *p, struct serial_rs485 *rs485, |
139 | struct ktermios *termios) |
140 | { |
141 | u32 lcr = dw8250_readl_ext(p, DW_UART_LCR_EXT); |
142 | |
143 | if (rs485->flags & SER_RS485_ADDRB) { |
144 | lcr |= DW_UART_LCR_EXT_DLS_E; |
145 | if (termios) |
146 | termios->c_cflag |= ADDRB; |
147 | |
148 | if (rs485->flags & SER_RS485_ADDR_RECV) { |
149 | u32 delta = p->rs485.flags ^ rs485->flags; |
150 | |
151 | /* |
152 | * rs485 (param) is equal to uart_port's rs485 only during init |
153 | * (during init, delta is not yet applicable). |
154 | */ |
155 | if (unlikely(&p->rs485 == rs485)) |
156 | delta = rs485->flags; |
157 | |
158 | if ((delta & SER_RS485_ADDR_RECV) || |
159 | (p->rs485.addr_recv != rs485->addr_recv)) |
160 | dw8250_update_rar(p, addr: rs485->addr_recv); |
161 | lcr |= DW_UART_LCR_EXT_ADDR_MATCH; |
162 | } else { |
163 | lcr &= ~DW_UART_LCR_EXT_ADDR_MATCH; |
164 | } |
165 | if (rs485->flags & SER_RS485_ADDR_DEST) { |
166 | /* |
167 | * Don't skip writes here as another endpoint could |
168 | * have changed communication line's destination |
169 | * address in between. |
170 | */ |
171 | dw8250_writel_ext(p, DW_UART_TAR, reg: rs485->addr_dest); |
172 | lcr |= DW_UART_LCR_EXT_SEND_ADDR; |
173 | } |
174 | } else { |
175 | lcr = 0; |
176 | } |
177 | dw8250_writel_ext(p, DW_UART_LCR_EXT, reg: lcr); |
178 | } |
179 | |
180 | static int dw8250_rs485_config(struct uart_port *p, struct ktermios *termios, |
181 | struct serial_rs485 *rs485) |
182 | { |
183 | u32 tcr; |
184 | |
185 | tcr = dw8250_readl_ext(p, DW_UART_TCR); |
186 | tcr &= ~DW_UART_TCR_XFER_MODE; |
187 | |
188 | if (rs485->flags & SER_RS485_ENABLED) { |
189 | tcr |= DW_UART_TCR_RS485_EN; |
190 | |
191 | if (rs485->flags & SER_RS485_RX_DURING_TX) |
192 | tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE; |
193 | else |
194 | tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE; |
195 | dw8250_writel_ext(p, DW_UART_DE_EN, reg: 1); |
196 | dw8250_writel_ext(p, DW_UART_RE_EN, reg: 1); |
197 | } else { |
198 | if (termios) |
199 | termios->c_cflag &= ~ADDRB; |
200 | |
201 | tcr &= ~DW_UART_TCR_RS485_EN; |
202 | } |
203 | |
204 | /* Reset to default polarity */ |
205 | tcr |= DW_UART_TCR_DE_POL; |
206 | tcr &= ~DW_UART_TCR_RE_POL; |
207 | |
208 | if (!(rs485->flags & SER_RS485_RTS_ON_SEND)) |
209 | tcr &= ~DW_UART_TCR_DE_POL; |
210 | if (device_property_read_bool(dev: p->dev, propname: "rs485-rx-active-high" )) |
211 | tcr |= DW_UART_TCR_RE_POL; |
212 | |
213 | dw8250_writel_ext(p, DW_UART_TCR, reg: tcr); |
214 | |
215 | /* Addressing mode can only be set up after TCR */ |
216 | if (rs485->flags & SER_RS485_ENABLED) |
217 | dw8250_rs485_set_addr(p, rs485, termios); |
218 | |
219 | return 0; |
220 | } |
221 | |
222 | /* |
223 | * Tests if RE_EN register can have non-zero value to see if RS-485 HW support |
224 | * is present. |
225 | */ |
226 | static bool dw8250_detect_rs485_hw(struct uart_port *p) |
227 | { |
228 | u32 reg; |
229 | |
230 | dw8250_writel_ext(p, DW_UART_RE_EN, reg: 1); |
231 | reg = dw8250_readl_ext(p, DW_UART_RE_EN); |
232 | dw8250_writel_ext(p, DW_UART_RE_EN, reg: 0); |
233 | return reg; |
234 | } |
235 | |
236 | static const struct serial_rs485 dw8250_rs485_supported = { |
237 | .flags = SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | SER_RS485_RTS_ON_SEND | |
238 | SER_RS485_RTS_AFTER_SEND | SER_RS485_ADDRB | SER_RS485_ADDR_RECV | |
239 | SER_RS485_ADDR_DEST, |
240 | }; |
241 | |
242 | void dw8250_setup_port(struct uart_port *p) |
243 | { |
244 | struct dw8250_port_data *pd = p->private_data; |
245 | struct dw8250_data *data = to_dw8250_data(data: pd); |
246 | struct uart_8250_port *up = up_to_u8250p(up: p); |
247 | u32 reg, old_dlf; |
248 | |
249 | pd->hw_rs485_support = dw8250_detect_rs485_hw(p); |
250 | if (pd->hw_rs485_support) { |
251 | p->rs485_config = dw8250_rs485_config; |
252 | up->lsr_save_mask = LSR_SAVE_FLAGS | DW_UART_LSR_ADDR_RCVD; |
253 | p->rs485_supported = dw8250_rs485_supported; |
254 | } else { |
255 | p->rs485_config = serial8250_em485_config; |
256 | p->rs485_supported = serial8250_em485_supported; |
257 | up->rs485_start_tx = serial8250_em485_start_tx; |
258 | up->rs485_stop_tx = serial8250_em485_stop_tx; |
259 | } |
260 | up->capabilities |= UART_CAP_NOTEMT; |
261 | |
262 | /* Preserve value written by firmware or bootloader */ |
263 | old_dlf = dw8250_readl_ext(p, DW_UART_DLF); |
264 | dw8250_writel_ext(p, DW_UART_DLF, reg: ~0U); |
265 | reg = dw8250_readl_ext(p, DW_UART_DLF); |
266 | dw8250_writel_ext(p, DW_UART_DLF, reg: old_dlf); |
267 | |
268 | if (reg) { |
269 | pd->dlf_size = fls(x: reg); |
270 | p->get_divisor = dw8250_get_divisor; |
271 | p->set_divisor = dw8250_set_divisor; |
272 | } |
273 | |
274 | reg = dw8250_readl_ext(p, DW_UART_UCV); |
275 | if (reg) |
276 | dev_dbg(p->dev, "Designware UART version %c.%c%c\n" , |
277 | (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); |
278 | |
279 | reg = dw8250_readl_ext(p, DW_UART_CPR); |
280 | if (!reg) { |
281 | reg = data->pdata->cpr_val; |
282 | dev_dbg(p->dev, "CPR is not available, using 0x%08x instead\n" , reg); |
283 | } |
284 | if (!reg) |
285 | return; |
286 | |
287 | /* Select the type based on FIFO */ |
288 | if (reg & DW_UART_CPR_FIFO_MODE) { |
289 | p->type = PORT_16550A; |
290 | p->flags |= UPF_FIXED_TYPE; |
291 | p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); |
292 | up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT; |
293 | } |
294 | |
295 | if (reg & DW_UART_CPR_AFCE_MODE) |
296 | up->capabilities |= UART_CAP_AFE; |
297 | |
298 | if (reg & DW_UART_CPR_SIR_MODE) |
299 | up->capabilities |= UART_CAP_IRDA; |
300 | } |
301 | EXPORT_SYMBOL_GPL(dw8250_setup_port); |
302 | |