1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * SiFive UART driver |
4 | * Copyright (C) 2018 Paul Walmsley <paul@pwsan.com> |
5 | * Copyright (C) 2018-2019 SiFive |
6 | * |
7 | * Based partially on: |
8 | * - drivers/tty/serial/pxa.c |
9 | * - drivers/tty/serial/amba-pl011.c |
10 | * - drivers/tty/serial/uartlite.c |
11 | * - drivers/tty/serial/omap-serial.c |
12 | * - drivers/pwm/pwm-sifive.c |
13 | * |
14 | * See the following sources for further documentation: |
15 | * - Chapter 19 "Universal Asynchronous Receiver/Transmitter (UART)" of |
16 | * SiFive FE310-G000 v2p3 |
17 | * - The tree/master/src/main/scala/devices/uart directory of |
18 | * https://github.com/sifive/sifive-blocks/ |
19 | * |
20 | * The SiFive UART design is not 8250-compatible. The following common |
21 | * features are not supported: |
22 | * - Word lengths other than 8 bits |
23 | * - Break handling |
24 | * - Parity |
25 | * - Flow control |
26 | * - Modem signals (DSR, RI, etc.) |
27 | * On the other hand, the design is free from the baggage of the 8250 |
28 | * programming model. |
29 | */ |
30 | |
31 | #include <linux/clk.h> |
32 | #include <linux/console.h> |
33 | #include <linux/delay.h> |
34 | #include <linux/init.h> |
35 | #include <linux/io.h> |
36 | #include <linux/irq.h> |
37 | #include <linux/module.h> |
38 | #include <linux/of.h> |
39 | #include <linux/of_irq.h> |
40 | #include <linux/platform_device.h> |
41 | #include <linux/serial_core.h> |
42 | #include <linux/serial_reg.h> |
43 | #include <linux/slab.h> |
44 | #include <linux/tty.h> |
45 | #include <linux/tty_flip.h> |
46 | |
47 | /* |
48 | * Register offsets |
49 | */ |
50 | |
51 | /* TXDATA */ |
52 | #define SIFIVE_SERIAL_TXDATA_OFFS 0x0 |
53 | #define SIFIVE_SERIAL_TXDATA_FULL_SHIFT 31 |
54 | #define SIFIVE_SERIAL_TXDATA_FULL_MASK (1 << SIFIVE_SERIAL_TXDATA_FULL_SHIFT) |
55 | #define SIFIVE_SERIAL_TXDATA_DATA_SHIFT 0 |
56 | #define SIFIVE_SERIAL_TXDATA_DATA_MASK (0xff << SIFIVE_SERIAL_TXDATA_DATA_SHIFT) |
57 | |
58 | /* RXDATA */ |
59 | #define SIFIVE_SERIAL_RXDATA_OFFS 0x4 |
60 | #define SIFIVE_SERIAL_RXDATA_EMPTY_SHIFT 31 |
61 | #define SIFIVE_SERIAL_RXDATA_EMPTY_MASK (1 << SIFIVE_SERIAL_RXDATA_EMPTY_SHIFT) |
62 | #define SIFIVE_SERIAL_RXDATA_DATA_SHIFT 0 |
63 | #define SIFIVE_SERIAL_RXDATA_DATA_MASK (0xff << SIFIVE_SERIAL_RXDATA_DATA_SHIFT) |
64 | |
65 | /* TXCTRL */ |
66 | #define SIFIVE_SERIAL_TXCTRL_OFFS 0x8 |
67 | #define SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT 16 |
68 | #define SIFIVE_SERIAL_TXCTRL_TXCNT_MASK (0x7 << SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT) |
69 | #define SIFIVE_SERIAL_TXCTRL_NSTOP_SHIFT 1 |
70 | #define SIFIVE_SERIAL_TXCTRL_NSTOP_MASK (1 << SIFIVE_SERIAL_TXCTRL_NSTOP_SHIFT) |
71 | #define SIFIVE_SERIAL_TXCTRL_TXEN_SHIFT 0 |
72 | #define SIFIVE_SERIAL_TXCTRL_TXEN_MASK (1 << SIFIVE_SERIAL_TXCTRL_TXEN_SHIFT) |
73 | |
74 | /* RXCTRL */ |
75 | #define SIFIVE_SERIAL_RXCTRL_OFFS 0xC |
76 | #define SIFIVE_SERIAL_RXCTRL_RXCNT_SHIFT 16 |
77 | #define SIFIVE_SERIAL_RXCTRL_RXCNT_MASK (0x7 << SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT) |
78 | #define SIFIVE_SERIAL_RXCTRL_RXEN_SHIFT 0 |
79 | #define SIFIVE_SERIAL_RXCTRL_RXEN_MASK (1 << SIFIVE_SERIAL_RXCTRL_RXEN_SHIFT) |
80 | |
81 | /* IE */ |
82 | #define SIFIVE_SERIAL_IE_OFFS 0x10 |
83 | #define SIFIVE_SERIAL_IE_RXWM_SHIFT 1 |
84 | #define SIFIVE_SERIAL_IE_RXWM_MASK (1 << SIFIVE_SERIAL_IE_RXWM_SHIFT) |
85 | #define SIFIVE_SERIAL_IE_TXWM_SHIFT 0 |
86 | #define SIFIVE_SERIAL_IE_TXWM_MASK (1 << SIFIVE_SERIAL_IE_TXWM_SHIFT) |
87 | |
88 | /* IP */ |
89 | #define SIFIVE_SERIAL_IP_OFFS 0x14 |
90 | #define SIFIVE_SERIAL_IP_RXWM_SHIFT 1 |
91 | #define SIFIVE_SERIAL_IP_RXWM_MASK (1 << SIFIVE_SERIAL_IP_RXWM_SHIFT) |
92 | #define SIFIVE_SERIAL_IP_TXWM_SHIFT 0 |
93 | #define SIFIVE_SERIAL_IP_TXWM_MASK (1 << SIFIVE_SERIAL_IP_TXWM_SHIFT) |
94 | |
95 | /* DIV */ |
96 | #define SIFIVE_SERIAL_DIV_OFFS 0x18 |
97 | #define SIFIVE_SERIAL_DIV_DIV_SHIFT 0 |
98 | #define SIFIVE_SERIAL_DIV_DIV_MASK (0xffff << SIFIVE_SERIAL_IP_DIV_SHIFT) |
99 | |
100 | /* |
101 | * Config macros |
102 | */ |
103 | |
104 | /* |
105 | * SIFIVE_SERIAL_MAX_PORTS: maximum number of UARTs on a device that can |
106 | * host a serial console |
107 | */ |
108 | #define SIFIVE_SERIAL_MAX_PORTS 8 |
109 | |
110 | /* |
111 | * SIFIVE_DEFAULT_BAUD_RATE: default baud rate that the driver should |
112 | * configure itself to use |
113 | */ |
114 | #define SIFIVE_DEFAULT_BAUD_RATE 115200 |
115 | |
116 | /* SIFIVE_SERIAL_NAME: our driver's name that we pass to the operating system */ |
117 | #define SIFIVE_SERIAL_NAME "sifive-serial" |
118 | |
119 | /* SIFIVE_TTY_PREFIX: tty name prefix for SiFive serial ports */ |
120 | #define SIFIVE_TTY_PREFIX "ttySIF" |
121 | |
122 | /* SIFIVE_TX_FIFO_DEPTH: depth of the TX FIFO (in bytes) */ |
123 | #define SIFIVE_TX_FIFO_DEPTH 8 |
124 | |
125 | /* SIFIVE_RX_FIFO_DEPTH: depth of the TX FIFO (in bytes) */ |
126 | #define SIFIVE_RX_FIFO_DEPTH 8 |
127 | |
128 | #if (SIFIVE_TX_FIFO_DEPTH != SIFIVE_RX_FIFO_DEPTH) |
129 | #error Driver does not support configurations with different TX, RX FIFO sizes |
130 | #endif |
131 | |
132 | /* |
133 | * |
134 | */ |
135 | |
136 | /** |
137 | * struct sifive_serial_port - driver-specific data extension to struct uart_port |
138 | * @port: struct uart_port embedded in this struct |
139 | * @dev: struct device * |
140 | * @ier: shadowed copy of the interrupt enable register |
141 | * @baud_rate: UART serial line rate (e.g., 115200 baud) |
142 | * @clk: reference to this device's clock |
143 | * @clk_notifier: clock rate change notifier for upstream clock changes |
144 | * |
145 | * Configuration data specific to this SiFive UART. |
146 | */ |
147 | struct sifive_serial_port { |
148 | struct uart_port port; |
149 | struct device *dev; |
150 | unsigned char ier; |
151 | unsigned long baud_rate; |
152 | struct clk *clk; |
153 | struct notifier_block clk_notifier; |
154 | }; |
155 | |
156 | /* |
157 | * Structure container-of macros |
158 | */ |
159 | |
160 | #define port_to_sifive_serial_port(p) (container_of((p), \ |
161 | struct sifive_serial_port, \ |
162 | port)) |
163 | |
164 | #define notifier_to_sifive_serial_port(nb) (container_of((nb), \ |
165 | struct sifive_serial_port, \ |
166 | clk_notifier)) |
167 | |
168 | /* |
169 | * Forward declarations |
170 | */ |
171 | static void sifive_serial_stop_tx(struct uart_port *port); |
172 | |
173 | /* |
174 | * Internal functions |
175 | */ |
176 | |
177 | /** |
178 | * __ssp_early_writel() - write to a SiFive serial port register (early) |
179 | * @port: pointer to a struct uart_port record |
180 | * @offs: register address offset from the IP block base address |
181 | * @v: value to write to the register |
182 | * |
183 | * Given a pointer @port to a struct uart_port record, write the value |
184 | * @v to the IP block register address offset @offs. This function is |
185 | * intended for early console use. |
186 | * |
187 | * Context: Intended to be used only by the earlyconsole code. |
188 | */ |
189 | static void __ssp_early_writel(u32 v, u16 offs, struct uart_port *port) |
190 | { |
191 | writel_relaxed(v, port->membase + offs); |
192 | } |
193 | |
194 | /** |
195 | * __ssp_early_readl() - read from a SiFive serial port register (early) |
196 | * @port: pointer to a struct uart_port record |
197 | * @offs: register address offset from the IP block base address |
198 | * |
199 | * Given a pointer @port to a struct uart_port record, read the |
200 | * contents of the IP block register located at offset @offs from the |
201 | * IP block base and return it. This function is intended for early |
202 | * console use. |
203 | * |
204 | * Context: Intended to be called only by the earlyconsole code or by |
205 | * __ssp_readl() or __ssp_writel() (in this driver) |
206 | * |
207 | * Returns: the register value read from the UART. |
208 | */ |
209 | static u32 __ssp_early_readl(struct uart_port *port, u16 offs) |
210 | { |
211 | return readl_relaxed(port->membase + offs); |
212 | } |
213 | |
214 | /** |
215 | * __ssp_writel() - write to a SiFive serial port register |
216 | * @v: value to write to the register |
217 | * @offs: register address offset from the IP block base address |
218 | * @ssp: pointer to a struct sifive_serial_port record |
219 | * |
220 | * Write the value @v to the IP block register located at offset @offs from the |
221 | * IP block base, given a pointer @ssp to a struct sifive_serial_port record. |
222 | * |
223 | * Context: Any context. |
224 | */ |
225 | static void __ssp_writel(u32 v, u16 offs, struct sifive_serial_port *ssp) |
226 | { |
227 | __ssp_early_writel(v, offs, port: &ssp->port); |
228 | } |
229 | |
230 | /** |
231 | * __ssp_readl() - read from a SiFive serial port register |
232 | * @ssp: pointer to a struct sifive_serial_port record |
233 | * @offs: register address offset from the IP block base address |
234 | * |
235 | * Read the contents of the IP block register located at offset @offs from the |
236 | * IP block base, given a pointer @ssp to a struct sifive_serial_port record. |
237 | * |
238 | * Context: Any context. |
239 | * |
240 | * Returns: the value of the UART register |
241 | */ |
242 | static u32 __ssp_readl(struct sifive_serial_port *ssp, u16 offs) |
243 | { |
244 | return __ssp_early_readl(port: &ssp->port, offs); |
245 | } |
246 | |
247 | /** |
248 | * sifive_serial_is_txfifo_full() - is the TXFIFO full? |
249 | * @ssp: pointer to a struct sifive_serial_port |
250 | * |
251 | * Read the transmit FIFO "full" bit, returning a non-zero value if the |
252 | * TX FIFO is full, or zero if space remains. Intended to be used to prevent |
253 | * writes to the TX FIFO when it's full. |
254 | * |
255 | * Returns: SIFIVE_SERIAL_TXDATA_FULL_MASK (non-zero) if the transmit FIFO |
256 | * is full, or 0 if space remains. |
257 | */ |
258 | static int sifive_serial_is_txfifo_full(struct sifive_serial_port *ssp) |
259 | { |
260 | return __ssp_readl(ssp, SIFIVE_SERIAL_TXDATA_OFFS) & |
261 | SIFIVE_SERIAL_TXDATA_FULL_MASK; |
262 | } |
263 | |
264 | /** |
265 | * __ssp_transmit_char() - enqueue a byte to transmit onto the TX FIFO |
266 | * @ssp: pointer to a struct sifive_serial_port |
267 | * @ch: character to transmit |
268 | * |
269 | * Enqueue a byte @ch onto the transmit FIFO, given a pointer @ssp to the |
270 | * struct sifive_serial_port * to transmit on. Caller should first check to |
271 | * ensure that the TXFIFO has space; see sifive_serial_is_txfifo_full(). |
272 | * |
273 | * Context: Any context. |
274 | */ |
275 | static void __ssp_transmit_char(struct sifive_serial_port *ssp, int ch) |
276 | { |
277 | __ssp_writel(v: ch, SIFIVE_SERIAL_TXDATA_OFFS, ssp); |
278 | } |
279 | |
280 | /** |
281 | * __ssp_transmit_chars() - enqueue multiple bytes onto the TX FIFO |
282 | * @ssp: pointer to a struct sifive_serial_port |
283 | * |
284 | * Transfer up to a TX FIFO size's worth of characters from the Linux serial |
285 | * transmit buffer to the SiFive UART TX FIFO. |
286 | * |
287 | * Context: Any context. Expects @ssp->port.lock to be held by caller. |
288 | */ |
289 | static void __ssp_transmit_chars(struct sifive_serial_port *ssp) |
290 | { |
291 | u8 ch; |
292 | |
293 | uart_port_tx_limited(&ssp->port, ch, SIFIVE_TX_FIFO_DEPTH, |
294 | true, |
295 | __ssp_transmit_char(ssp, ch), |
296 | ({})); |
297 | } |
298 | |
299 | /** |
300 | * __ssp_enable_txwm() - enable transmit watermark interrupts |
301 | * @ssp: pointer to a struct sifive_serial_port |
302 | * |
303 | * Enable interrupt generation when the transmit FIFO watermark is reached |
304 | * on the SiFive UART referred to by @ssp. |
305 | */ |
306 | static void __ssp_enable_txwm(struct sifive_serial_port *ssp) |
307 | { |
308 | if (ssp->ier & SIFIVE_SERIAL_IE_TXWM_MASK) |
309 | return; |
310 | |
311 | ssp->ier |= SIFIVE_SERIAL_IE_TXWM_MASK; |
312 | __ssp_writel(v: ssp->ier, SIFIVE_SERIAL_IE_OFFS, ssp); |
313 | } |
314 | |
315 | /** |
316 | * __ssp_enable_rxwm() - enable receive watermark interrupts |
317 | * @ssp: pointer to a struct sifive_serial_port |
318 | * |
319 | * Enable interrupt generation when the receive FIFO watermark is reached |
320 | * on the SiFive UART referred to by @ssp. |
321 | */ |
322 | static void __ssp_enable_rxwm(struct sifive_serial_port *ssp) |
323 | { |
324 | if (ssp->ier & SIFIVE_SERIAL_IE_RXWM_MASK) |
325 | return; |
326 | |
327 | ssp->ier |= SIFIVE_SERIAL_IE_RXWM_MASK; |
328 | __ssp_writel(v: ssp->ier, SIFIVE_SERIAL_IE_OFFS, ssp); |
329 | } |
330 | |
331 | /** |
332 | * __ssp_disable_txwm() - disable transmit watermark interrupts |
333 | * @ssp: pointer to a struct sifive_serial_port |
334 | * |
335 | * Disable interrupt generation when the transmit FIFO watermark is reached |
336 | * on the UART referred to by @ssp. |
337 | */ |
338 | static void __ssp_disable_txwm(struct sifive_serial_port *ssp) |
339 | { |
340 | if (!(ssp->ier & SIFIVE_SERIAL_IE_TXWM_MASK)) |
341 | return; |
342 | |
343 | ssp->ier &= ~SIFIVE_SERIAL_IE_TXWM_MASK; |
344 | __ssp_writel(v: ssp->ier, SIFIVE_SERIAL_IE_OFFS, ssp); |
345 | } |
346 | |
347 | /** |
348 | * __ssp_disable_rxwm() - disable receive watermark interrupts |
349 | * @ssp: pointer to a struct sifive_serial_port |
350 | * |
351 | * Disable interrupt generation when the receive FIFO watermark is reached |
352 | * on the UART referred to by @ssp. |
353 | */ |
354 | static void __ssp_disable_rxwm(struct sifive_serial_port *ssp) |
355 | { |
356 | if (!(ssp->ier & SIFIVE_SERIAL_IE_RXWM_MASK)) |
357 | return; |
358 | |
359 | ssp->ier &= ~SIFIVE_SERIAL_IE_RXWM_MASK; |
360 | __ssp_writel(v: ssp->ier, SIFIVE_SERIAL_IE_OFFS, ssp); |
361 | } |
362 | |
363 | /** |
364 | * __ssp_receive_char() - receive a byte from the UART |
365 | * @ssp: pointer to a struct sifive_serial_port |
366 | * @is_empty: char pointer to return whether the RX FIFO is empty |
367 | * |
368 | * Try to read a byte from the SiFive UART RX FIFO, referenced by |
369 | * @ssp, and to return it. Also returns the RX FIFO empty bit in |
370 | * the char pointed to by @ch. The caller must pass the byte back to the |
371 | * Linux serial layer if needed. |
372 | * |
373 | * Returns: the byte read from the UART RX FIFO. |
374 | */ |
375 | static char __ssp_receive_char(struct sifive_serial_port *ssp, char *is_empty) |
376 | { |
377 | u32 v; |
378 | u8 ch; |
379 | |
380 | v = __ssp_readl(ssp, SIFIVE_SERIAL_RXDATA_OFFS); |
381 | |
382 | if (!is_empty) |
383 | WARN_ON(1); |
384 | else |
385 | *is_empty = (v & SIFIVE_SERIAL_RXDATA_EMPTY_MASK) >> |
386 | SIFIVE_SERIAL_RXDATA_EMPTY_SHIFT; |
387 | |
388 | ch = (v & SIFIVE_SERIAL_RXDATA_DATA_MASK) >> |
389 | SIFIVE_SERIAL_RXDATA_DATA_SHIFT; |
390 | |
391 | return ch; |
392 | } |
393 | |
394 | /** |
395 | * __ssp_receive_chars() - receive multiple bytes from the UART |
396 | * @ssp: pointer to a struct sifive_serial_port |
397 | * |
398 | * Receive up to an RX FIFO's worth of bytes from the SiFive UART referred |
399 | * to by @ssp and pass them up to the Linux serial layer. |
400 | * |
401 | * Context: Expects ssp->port.lock to be held by caller. |
402 | */ |
403 | static void __ssp_receive_chars(struct sifive_serial_port *ssp) |
404 | { |
405 | char is_empty; |
406 | int c; |
407 | u8 ch; |
408 | |
409 | for (c = SIFIVE_RX_FIFO_DEPTH; c > 0; --c) { |
410 | ch = __ssp_receive_char(ssp, is_empty: &is_empty); |
411 | if (is_empty) |
412 | break; |
413 | |
414 | ssp->port.icount.rx++; |
415 | if (!uart_prepare_sysrq_char(port: &ssp->port, ch)) |
416 | uart_insert_char(port: &ssp->port, status: 0, overrun: 0, ch, TTY_NORMAL); |
417 | } |
418 | |
419 | tty_flip_buffer_push(port: &ssp->port.state->port); |
420 | } |
421 | |
422 | /** |
423 | * __ssp_update_div() - calculate the divisor setting by the line rate |
424 | * @ssp: pointer to a struct sifive_serial_port |
425 | * |
426 | * Calculate the appropriate value of the clock divisor for the UART |
427 | * and target line rate referred to by @ssp and write it into the |
428 | * hardware. |
429 | */ |
430 | static void __ssp_update_div(struct sifive_serial_port *ssp) |
431 | { |
432 | u16 div; |
433 | |
434 | div = DIV_ROUND_UP(ssp->port.uartclk, ssp->baud_rate) - 1; |
435 | |
436 | __ssp_writel(v: div, SIFIVE_SERIAL_DIV_OFFS, ssp); |
437 | } |
438 | |
439 | /** |
440 | * __ssp_update_baud_rate() - set the UART "baud rate" |
441 | * @ssp: pointer to a struct sifive_serial_port |
442 | * @rate: new target bit rate |
443 | * |
444 | * Calculate the UART divisor value for the target bit rate @rate for the |
445 | * SiFive UART described by @ssp and program it into the UART. There may |
446 | * be some error between the target bit rate and the actual bit rate implemented |
447 | * by the UART due to clock ratio granularity. |
448 | */ |
449 | static void __ssp_update_baud_rate(struct sifive_serial_port *ssp, |
450 | unsigned int rate) |
451 | { |
452 | if (ssp->baud_rate == rate) |
453 | return; |
454 | |
455 | ssp->baud_rate = rate; |
456 | __ssp_update_div(ssp); |
457 | } |
458 | |
459 | /** |
460 | * __ssp_set_stop_bits() - set the number of stop bits |
461 | * @ssp: pointer to a struct sifive_serial_port |
462 | * @nstop: 1 or 2 (stop bits) |
463 | * |
464 | * Program the SiFive UART referred to by @ssp to use @nstop stop bits. |
465 | */ |
466 | static void __ssp_set_stop_bits(struct sifive_serial_port *ssp, char nstop) |
467 | { |
468 | u32 v; |
469 | |
470 | if (nstop < 1 || nstop > 2) { |
471 | WARN_ON(1); |
472 | return; |
473 | } |
474 | |
475 | v = __ssp_readl(ssp, SIFIVE_SERIAL_TXCTRL_OFFS); |
476 | v &= ~SIFIVE_SERIAL_TXCTRL_NSTOP_MASK; |
477 | v |= (nstop - 1) << SIFIVE_SERIAL_TXCTRL_NSTOP_SHIFT; |
478 | __ssp_writel(v, SIFIVE_SERIAL_TXCTRL_OFFS, ssp); |
479 | } |
480 | |
481 | /** |
482 | * __ssp_wait_for_xmitr() - wait for an empty slot on the TX FIFO |
483 | * @ssp: pointer to a struct sifive_serial_port |
484 | * |
485 | * Delay while the UART TX FIFO referred to by @ssp is marked as full. |
486 | * |
487 | * Context: Any context. |
488 | */ |
489 | static void __maybe_unused __ssp_wait_for_xmitr(struct sifive_serial_port *ssp) |
490 | { |
491 | while (sifive_serial_is_txfifo_full(ssp)) |
492 | udelay(1); /* XXX Could probably be more intelligent here */ |
493 | } |
494 | |
495 | /* |
496 | * Linux serial API functions |
497 | */ |
498 | |
499 | static void sifive_serial_stop_tx(struct uart_port *port) |
500 | { |
501 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
502 | |
503 | __ssp_disable_txwm(ssp); |
504 | } |
505 | |
506 | static void sifive_serial_stop_rx(struct uart_port *port) |
507 | { |
508 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
509 | |
510 | __ssp_disable_rxwm(ssp); |
511 | } |
512 | |
513 | static void sifive_serial_start_tx(struct uart_port *port) |
514 | { |
515 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
516 | |
517 | __ssp_enable_txwm(ssp); |
518 | } |
519 | |
520 | static irqreturn_t sifive_serial_irq(int irq, void *dev_id) |
521 | { |
522 | struct sifive_serial_port *ssp = dev_id; |
523 | u32 ip; |
524 | |
525 | uart_port_lock(up: &ssp->port); |
526 | |
527 | ip = __ssp_readl(ssp, SIFIVE_SERIAL_IP_OFFS); |
528 | if (!ip) { |
529 | uart_port_unlock(up: &ssp->port); |
530 | return IRQ_NONE; |
531 | } |
532 | |
533 | if (ip & SIFIVE_SERIAL_IP_RXWM_MASK) |
534 | __ssp_receive_chars(ssp); |
535 | if (ip & SIFIVE_SERIAL_IP_TXWM_MASK) |
536 | __ssp_transmit_chars(ssp); |
537 | |
538 | uart_unlock_and_check_sysrq(port: &ssp->port); |
539 | |
540 | return IRQ_HANDLED; |
541 | } |
542 | |
543 | static unsigned int sifive_serial_tx_empty(struct uart_port *port) |
544 | { |
545 | return TIOCSER_TEMT; |
546 | } |
547 | |
548 | static unsigned int sifive_serial_get_mctrl(struct uart_port *port) |
549 | { |
550 | return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR; |
551 | } |
552 | |
553 | static void sifive_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) |
554 | { |
555 | /* IP block does not support these signals */ |
556 | } |
557 | |
558 | static void sifive_serial_break_ctl(struct uart_port *port, int break_state) |
559 | { |
560 | /* IP block does not support sending a break */ |
561 | } |
562 | |
563 | static int sifive_serial_startup(struct uart_port *port) |
564 | { |
565 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
566 | |
567 | __ssp_enable_rxwm(ssp); |
568 | |
569 | return 0; |
570 | } |
571 | |
572 | static void sifive_serial_shutdown(struct uart_port *port) |
573 | { |
574 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
575 | |
576 | __ssp_disable_rxwm(ssp); |
577 | __ssp_disable_txwm(ssp); |
578 | } |
579 | |
580 | /** |
581 | * sifive_serial_clk_notifier() - clock post-rate-change notifier |
582 | * @nb: pointer to the struct notifier_block, from the notifier code |
583 | * @event: event mask from the notifier code |
584 | * @data: pointer to the struct clk_notifier_data from the notifier code |
585 | * |
586 | * On the V0 SoC, the UART IP block is derived from the CPU clock source |
587 | * after a synchronous divide-by-two divider, so any CPU clock rate change |
588 | * requires the UART baud rate to be updated. This presumably corrupts any |
589 | * serial word currently being transmitted or received. In order to avoid |
590 | * corrupting the output data stream, we drain the transmit queue before |
591 | * allowing the clock's rate to be changed. |
592 | */ |
593 | static int sifive_serial_clk_notifier(struct notifier_block *nb, |
594 | unsigned long event, void *data) |
595 | { |
596 | struct clk_notifier_data *cnd = data; |
597 | struct sifive_serial_port *ssp = notifier_to_sifive_serial_port(nb); |
598 | |
599 | if (event == PRE_RATE_CHANGE) { |
600 | /* |
601 | * The TX watermark is always set to 1 by this driver, which |
602 | * means that the TX busy bit will lower when there are 0 bytes |
603 | * left in the TX queue -- in other words, when the TX FIFO is |
604 | * empty. |
605 | */ |
606 | __ssp_wait_for_xmitr(ssp); |
607 | /* |
608 | * On the cycle the TX FIFO goes empty there is still a full |
609 | * UART frame left to be transmitted in the shift register. |
610 | * The UART provides no way for software to directly determine |
611 | * when that last frame has been transmitted, so we just sleep |
612 | * here instead. As we're not tracking the number of stop bits |
613 | * they're just worst cased here. The rest of the serial |
614 | * framing parameters aren't configurable by software. |
615 | */ |
616 | udelay(DIV_ROUND_UP(12 * 1000 * 1000, ssp->baud_rate)); |
617 | } |
618 | |
619 | if (event == POST_RATE_CHANGE && ssp->port.uartclk != cnd->new_rate) { |
620 | ssp->port.uartclk = cnd->new_rate; |
621 | __ssp_update_div(ssp); |
622 | } |
623 | |
624 | return NOTIFY_OK; |
625 | } |
626 | |
627 | static void sifive_serial_set_termios(struct uart_port *port, |
628 | struct ktermios *termios, |
629 | const struct ktermios *old) |
630 | { |
631 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
632 | unsigned long flags; |
633 | u32 v, old_v; |
634 | int rate; |
635 | char nstop; |
636 | |
637 | if ((termios->c_cflag & CSIZE) != CS8) { |
638 | dev_err_once(ssp->port.dev, "only 8-bit words supported\n" ); |
639 | termios->c_cflag &= ~CSIZE; |
640 | termios->c_cflag |= CS8; |
641 | } |
642 | if (termios->c_iflag & (INPCK | PARMRK)) |
643 | dev_err_once(ssp->port.dev, "parity checking not supported\n" ); |
644 | if (termios->c_iflag & BRKINT) |
645 | dev_err_once(ssp->port.dev, "BREAK detection not supported\n" ); |
646 | termios->c_iflag &= ~(INPCK|PARMRK|BRKINT); |
647 | |
648 | /* Set number of stop bits */ |
649 | nstop = (termios->c_cflag & CSTOPB) ? 2 : 1; |
650 | __ssp_set_stop_bits(ssp, nstop); |
651 | |
652 | /* Set line rate */ |
653 | rate = uart_get_baud_rate(port, termios, old, min: 0, |
654 | max: ssp->port.uartclk / 16); |
655 | __ssp_update_baud_rate(ssp, rate); |
656 | |
657 | uart_port_lock_irqsave(up: &ssp->port, flags: &flags); |
658 | |
659 | /* Update the per-port timeout */ |
660 | uart_update_timeout(port, cflag: termios->c_cflag, baud: rate); |
661 | |
662 | ssp->port.read_status_mask = 0; |
663 | |
664 | /* Ignore all characters if CREAD is not set */ |
665 | v = __ssp_readl(ssp, SIFIVE_SERIAL_RXCTRL_OFFS); |
666 | old_v = v; |
667 | if ((termios->c_cflag & CREAD) == 0) |
668 | v &= SIFIVE_SERIAL_RXCTRL_RXEN_MASK; |
669 | else |
670 | v |= SIFIVE_SERIAL_RXCTRL_RXEN_MASK; |
671 | if (v != old_v) |
672 | __ssp_writel(v, SIFIVE_SERIAL_RXCTRL_OFFS, ssp); |
673 | |
674 | uart_port_unlock_irqrestore(up: &ssp->port, flags); |
675 | } |
676 | |
677 | static void sifive_serial_release_port(struct uart_port *port) |
678 | { |
679 | } |
680 | |
681 | static int sifive_serial_request_port(struct uart_port *port) |
682 | { |
683 | return 0; |
684 | } |
685 | |
686 | static void sifive_serial_config_port(struct uart_port *port, int flags) |
687 | { |
688 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
689 | |
690 | ssp->port.type = PORT_SIFIVE_V0; |
691 | } |
692 | |
693 | static int sifive_serial_verify_port(struct uart_port *port, |
694 | struct serial_struct *ser) |
695 | { |
696 | return -EINVAL; |
697 | } |
698 | |
699 | static const char *sifive_serial_type(struct uart_port *port) |
700 | { |
701 | return port->type == PORT_SIFIVE_V0 ? "SiFive UART v0" : NULL; |
702 | } |
703 | |
704 | #ifdef CONFIG_CONSOLE_POLL |
705 | static int sifive_serial_poll_get_char(struct uart_port *port) |
706 | { |
707 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
708 | char is_empty, ch; |
709 | |
710 | ch = __ssp_receive_char(ssp, is_empty: &is_empty); |
711 | if (is_empty) |
712 | return NO_POLL_CHAR; |
713 | |
714 | return ch; |
715 | } |
716 | |
717 | static void sifive_serial_poll_put_char(struct uart_port *port, |
718 | unsigned char c) |
719 | { |
720 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
721 | |
722 | __ssp_wait_for_xmitr(ssp); |
723 | __ssp_transmit_char(ssp, ch: c); |
724 | } |
725 | #endif /* CONFIG_CONSOLE_POLL */ |
726 | |
727 | /* |
728 | * Early console support |
729 | */ |
730 | |
731 | #ifdef CONFIG_SERIAL_EARLYCON |
732 | static void early_sifive_serial_putc(struct uart_port *port, unsigned char c) |
733 | { |
734 | while (__ssp_early_readl(port, SIFIVE_SERIAL_TXDATA_OFFS) & |
735 | SIFIVE_SERIAL_TXDATA_FULL_MASK) |
736 | cpu_relax(); |
737 | |
738 | __ssp_early_writel(v: c, SIFIVE_SERIAL_TXDATA_OFFS, port); |
739 | } |
740 | |
741 | static void early_sifive_serial_write(struct console *con, const char *s, |
742 | unsigned int n) |
743 | { |
744 | struct earlycon_device *dev = con->data; |
745 | struct uart_port *port = &dev->port; |
746 | |
747 | uart_console_write(port, s, count: n, putchar: early_sifive_serial_putc); |
748 | } |
749 | |
750 | static int __init early_sifive_serial_setup(struct earlycon_device *dev, |
751 | const char *options) |
752 | { |
753 | struct uart_port *port = &dev->port; |
754 | |
755 | if (!port->membase) |
756 | return -ENODEV; |
757 | |
758 | dev->con->write = early_sifive_serial_write; |
759 | |
760 | return 0; |
761 | } |
762 | |
763 | OF_EARLYCON_DECLARE(sifive, "sifive,uart0" , early_sifive_serial_setup); |
764 | OF_EARLYCON_DECLARE(sifive, "sifive,fu540-c000-uart0" , |
765 | early_sifive_serial_setup); |
766 | #endif /* CONFIG_SERIAL_EARLYCON */ |
767 | |
768 | /* |
769 | * Linux console interface |
770 | */ |
771 | |
772 | #ifdef CONFIG_SERIAL_SIFIVE_CONSOLE |
773 | |
774 | static struct sifive_serial_port *sifive_serial_console_ports[SIFIVE_SERIAL_MAX_PORTS]; |
775 | |
776 | static void sifive_serial_console_putchar(struct uart_port *port, unsigned char ch) |
777 | { |
778 | struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); |
779 | |
780 | __ssp_wait_for_xmitr(ssp); |
781 | __ssp_transmit_char(ssp, ch); |
782 | } |
783 | |
784 | static void sifive_serial_console_write(struct console *co, const char *s, |
785 | unsigned int count) |
786 | { |
787 | struct sifive_serial_port *ssp = sifive_serial_console_ports[co->index]; |
788 | unsigned long flags; |
789 | unsigned int ier; |
790 | int locked = 1; |
791 | |
792 | if (!ssp) |
793 | return; |
794 | |
795 | if (oops_in_progress) |
796 | locked = uart_port_trylock_irqsave(up: &ssp->port, flags: &flags); |
797 | else |
798 | uart_port_lock_irqsave(up: &ssp->port, flags: &flags); |
799 | |
800 | ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS); |
801 | __ssp_writel(v: 0, SIFIVE_SERIAL_IE_OFFS, ssp); |
802 | |
803 | uart_console_write(port: &ssp->port, s, count, putchar: sifive_serial_console_putchar); |
804 | |
805 | __ssp_writel(v: ier, SIFIVE_SERIAL_IE_OFFS, ssp); |
806 | |
807 | if (locked) |
808 | uart_port_unlock_irqrestore(up: &ssp->port, flags); |
809 | } |
810 | |
811 | static int sifive_serial_console_setup(struct console *co, char *options) |
812 | { |
813 | struct sifive_serial_port *ssp; |
814 | int baud = SIFIVE_DEFAULT_BAUD_RATE; |
815 | int bits = 8; |
816 | int parity = 'n'; |
817 | int flow = 'n'; |
818 | |
819 | if (co->index < 0 || co->index >= SIFIVE_SERIAL_MAX_PORTS) |
820 | return -ENODEV; |
821 | |
822 | ssp = sifive_serial_console_ports[co->index]; |
823 | if (!ssp) |
824 | return -ENODEV; |
825 | |
826 | if (options) |
827 | uart_parse_options(options, baud: &baud, parity: &parity, bits: &bits, flow: &flow); |
828 | |
829 | return uart_set_options(port: &ssp->port, co, baud, parity, bits, flow); |
830 | } |
831 | |
832 | static struct uart_driver sifive_serial_uart_driver; |
833 | |
834 | static struct console sifive_serial_console = { |
835 | .name = SIFIVE_TTY_PREFIX, |
836 | .write = sifive_serial_console_write, |
837 | .device = uart_console_device, |
838 | .setup = sifive_serial_console_setup, |
839 | .flags = CON_PRINTBUFFER, |
840 | .index = -1, |
841 | .data = &sifive_serial_uart_driver, |
842 | }; |
843 | |
844 | static int __init sifive_console_init(void) |
845 | { |
846 | register_console(&sifive_serial_console); |
847 | return 0; |
848 | } |
849 | |
850 | console_initcall(sifive_console_init); |
851 | |
852 | static void __ssp_add_console_port(struct sifive_serial_port *ssp) |
853 | { |
854 | sifive_serial_console_ports[ssp->port.line] = ssp; |
855 | } |
856 | |
857 | static void __ssp_remove_console_port(struct sifive_serial_port *ssp) |
858 | { |
859 | sifive_serial_console_ports[ssp->port.line] = NULL; |
860 | } |
861 | |
862 | #define SIFIVE_SERIAL_CONSOLE (&sifive_serial_console) |
863 | |
864 | #else |
865 | |
866 | #define SIFIVE_SERIAL_CONSOLE NULL |
867 | |
868 | static void __ssp_add_console_port(struct sifive_serial_port *ssp) |
869 | {} |
870 | static void __ssp_remove_console_port(struct sifive_serial_port *ssp) |
871 | {} |
872 | |
873 | #endif |
874 | |
875 | static const struct uart_ops sifive_serial_uops = { |
876 | .tx_empty = sifive_serial_tx_empty, |
877 | .set_mctrl = sifive_serial_set_mctrl, |
878 | .get_mctrl = sifive_serial_get_mctrl, |
879 | .stop_tx = sifive_serial_stop_tx, |
880 | .start_tx = sifive_serial_start_tx, |
881 | .stop_rx = sifive_serial_stop_rx, |
882 | .break_ctl = sifive_serial_break_ctl, |
883 | .startup = sifive_serial_startup, |
884 | .shutdown = sifive_serial_shutdown, |
885 | .set_termios = sifive_serial_set_termios, |
886 | .type = sifive_serial_type, |
887 | .release_port = sifive_serial_release_port, |
888 | .request_port = sifive_serial_request_port, |
889 | .config_port = sifive_serial_config_port, |
890 | .verify_port = sifive_serial_verify_port, |
891 | #ifdef CONFIG_CONSOLE_POLL |
892 | .poll_get_char = sifive_serial_poll_get_char, |
893 | .poll_put_char = sifive_serial_poll_put_char, |
894 | #endif |
895 | }; |
896 | |
897 | static struct uart_driver sifive_serial_uart_driver = { |
898 | .owner = THIS_MODULE, |
899 | .driver_name = SIFIVE_SERIAL_NAME, |
900 | .dev_name = SIFIVE_TTY_PREFIX, |
901 | .nr = SIFIVE_SERIAL_MAX_PORTS, |
902 | .cons = SIFIVE_SERIAL_CONSOLE, |
903 | }; |
904 | |
905 | static int sifive_serial_probe(struct platform_device *pdev) |
906 | { |
907 | struct sifive_serial_port *ssp; |
908 | struct resource *mem; |
909 | struct clk *clk; |
910 | void __iomem *base; |
911 | int irq, id, r; |
912 | |
913 | irq = platform_get_irq(pdev, 0); |
914 | if (irq < 0) |
915 | return -EPROBE_DEFER; |
916 | |
917 | base = devm_platform_get_and_ioremap_resource(pdev, index: 0, res: &mem); |
918 | if (IS_ERR(ptr: base)) |
919 | return PTR_ERR(ptr: base); |
920 | |
921 | clk = devm_clk_get_enabled(dev: &pdev->dev, NULL); |
922 | if (IS_ERR(ptr: clk)) { |
923 | dev_err(&pdev->dev, "unable to find controller clock\n" ); |
924 | return PTR_ERR(ptr: clk); |
925 | } |
926 | |
927 | id = of_alias_get_id(np: pdev->dev.of_node, stem: "serial" ); |
928 | if (id < 0) { |
929 | dev_err(&pdev->dev, "missing aliases entry\n" ); |
930 | return id; |
931 | } |
932 | |
933 | #ifdef CONFIG_SERIAL_SIFIVE_CONSOLE |
934 | if (id > SIFIVE_SERIAL_MAX_PORTS) { |
935 | dev_err(&pdev->dev, "too many UARTs (%d)\n" , id); |
936 | return -EINVAL; |
937 | } |
938 | #endif |
939 | |
940 | ssp = devm_kzalloc(dev: &pdev->dev, size: sizeof(*ssp), GFP_KERNEL); |
941 | if (!ssp) |
942 | return -ENOMEM; |
943 | |
944 | ssp->port.dev = &pdev->dev; |
945 | ssp->port.type = PORT_SIFIVE_V0; |
946 | ssp->port.iotype = UPIO_MEM; |
947 | ssp->port.irq = irq; |
948 | ssp->port.fifosize = SIFIVE_TX_FIFO_DEPTH; |
949 | ssp->port.ops = &sifive_serial_uops; |
950 | ssp->port.line = id; |
951 | ssp->port.mapbase = mem->start; |
952 | ssp->port.membase = base; |
953 | ssp->dev = &pdev->dev; |
954 | ssp->clk = clk; |
955 | ssp->clk_notifier.notifier_call = sifive_serial_clk_notifier; |
956 | |
957 | r = clk_notifier_register(clk: ssp->clk, nb: &ssp->clk_notifier); |
958 | if (r) { |
959 | dev_err(&pdev->dev, "could not register clock notifier: %d\n" , |
960 | r); |
961 | goto probe_out1; |
962 | } |
963 | |
964 | /* Set up clock divider */ |
965 | ssp->port.uartclk = clk_get_rate(clk: ssp->clk); |
966 | ssp->baud_rate = SIFIVE_DEFAULT_BAUD_RATE; |
967 | __ssp_update_div(ssp); |
968 | |
969 | platform_set_drvdata(pdev, data: ssp); |
970 | |
971 | /* Enable transmits and set the watermark level to 1 */ |
972 | __ssp_writel(v: (1 << SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT) | |
973 | SIFIVE_SERIAL_TXCTRL_TXEN_MASK, |
974 | SIFIVE_SERIAL_TXCTRL_OFFS, ssp); |
975 | |
976 | /* Enable receives and set the watermark level to 0 */ |
977 | __ssp_writel(v: (0 << SIFIVE_SERIAL_RXCTRL_RXCNT_SHIFT) | |
978 | SIFIVE_SERIAL_RXCTRL_RXEN_MASK, |
979 | SIFIVE_SERIAL_RXCTRL_OFFS, ssp); |
980 | |
981 | r = request_irq(irq: ssp->port.irq, handler: sifive_serial_irq, flags: ssp->port.irqflags, |
982 | name: dev_name(dev: &pdev->dev), dev: ssp); |
983 | if (r) { |
984 | dev_err(&pdev->dev, "could not attach interrupt: %d\n" , r); |
985 | goto probe_out2; |
986 | } |
987 | |
988 | __ssp_add_console_port(ssp); |
989 | |
990 | r = uart_add_one_port(reg: &sifive_serial_uart_driver, port: &ssp->port); |
991 | if (r != 0) { |
992 | dev_err(&pdev->dev, "could not add uart: %d\n" , r); |
993 | goto probe_out3; |
994 | } |
995 | |
996 | return 0; |
997 | |
998 | probe_out3: |
999 | __ssp_remove_console_port(ssp); |
1000 | free_irq(ssp->port.irq, ssp); |
1001 | probe_out2: |
1002 | clk_notifier_unregister(clk: ssp->clk, nb: &ssp->clk_notifier); |
1003 | probe_out1: |
1004 | return r; |
1005 | } |
1006 | |
1007 | static void sifive_serial_remove(struct platform_device *dev) |
1008 | { |
1009 | struct sifive_serial_port *ssp = platform_get_drvdata(pdev: dev); |
1010 | |
1011 | __ssp_remove_console_port(ssp); |
1012 | uart_remove_one_port(reg: &sifive_serial_uart_driver, port: &ssp->port); |
1013 | free_irq(ssp->port.irq, ssp); |
1014 | clk_notifier_unregister(clk: ssp->clk, nb: &ssp->clk_notifier); |
1015 | } |
1016 | |
1017 | static int sifive_serial_suspend(struct device *dev) |
1018 | { |
1019 | struct sifive_serial_port *ssp = dev_get_drvdata(dev); |
1020 | |
1021 | return uart_suspend_port(reg: &sifive_serial_uart_driver, port: &ssp->port); |
1022 | } |
1023 | |
1024 | static int sifive_serial_resume(struct device *dev) |
1025 | { |
1026 | struct sifive_serial_port *ssp = dev_get_drvdata(dev); |
1027 | |
1028 | return uart_resume_port(reg: &sifive_serial_uart_driver, port: &ssp->port); |
1029 | } |
1030 | |
1031 | static DEFINE_SIMPLE_DEV_PM_OPS(sifive_uart_pm_ops, sifive_serial_suspend, |
1032 | sifive_serial_resume); |
1033 | |
1034 | static const struct of_device_id sifive_serial_of_match[] = { |
1035 | { .compatible = "sifive,fu540-c000-uart0" }, |
1036 | { .compatible = "sifive,uart0" }, |
1037 | {}, |
1038 | }; |
1039 | MODULE_DEVICE_TABLE(of, sifive_serial_of_match); |
1040 | |
1041 | static struct platform_driver sifive_serial_platform_driver = { |
1042 | .probe = sifive_serial_probe, |
1043 | .remove_new = sifive_serial_remove, |
1044 | .driver = { |
1045 | .name = SIFIVE_SERIAL_NAME, |
1046 | .pm = pm_sleep_ptr(&sifive_uart_pm_ops), |
1047 | .of_match_table = sifive_serial_of_match, |
1048 | }, |
1049 | }; |
1050 | |
1051 | static int __init sifive_serial_init(void) |
1052 | { |
1053 | int r; |
1054 | |
1055 | r = uart_register_driver(uart: &sifive_serial_uart_driver); |
1056 | if (r) |
1057 | goto init_out1; |
1058 | |
1059 | r = platform_driver_register(&sifive_serial_platform_driver); |
1060 | if (r) |
1061 | goto init_out2; |
1062 | |
1063 | return 0; |
1064 | |
1065 | init_out2: |
1066 | uart_unregister_driver(uart: &sifive_serial_uart_driver); |
1067 | init_out1: |
1068 | return r; |
1069 | } |
1070 | |
1071 | static void __exit sifive_serial_exit(void) |
1072 | { |
1073 | platform_driver_unregister(&sifive_serial_platform_driver); |
1074 | uart_unregister_driver(uart: &sifive_serial_uart_driver); |
1075 | } |
1076 | |
1077 | module_init(sifive_serial_init); |
1078 | module_exit(sifive_serial_exit); |
1079 | |
1080 | MODULE_DESCRIPTION("SiFive UART serial driver" ); |
1081 | MODULE_LICENSE("GPL" ); |
1082 | MODULE_AUTHOR("Paul Walmsley <paul@pwsan.com>" ); |
1083 | |