blob: 395df8c7e1d551262a6c0cf08e03ce5b880868d1 [file] [log] [blame]
Greg Kroah-Hartmane3b3d0f2017-11-06 18:11:51 +01001// SPDX-License-Identifier: GPL-2.0+
Jingchang Luc9e2e942013-06-07 09:20:40 +08002/*
3 * Freescale lpuart serial port driver
4 *
Jingchang Lu380c9662014-07-14 17:41:11 +08005 * Copyright 2012-2014 Freescale Semiconductor, Inc.
Jingchang Luc9e2e942013-06-07 09:20:40 +08006 */
7
8#if defined(CONFIG_SERIAL_FSL_LPUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
9#define SUPPORT_SYSRQ
10#endif
11
Yuan Yaof1cd8c82014-02-17 13:28:07 +080012#include <linux/clk.h>
13#include <linux/console.h>
14#include <linux/dma-mapping.h>
15#include <linux/dmaengine.h>
16#include <linux/dmapool.h>
Jingchang Luc9e2e942013-06-07 09:20:40 +080017#include <linux/io.h>
18#include <linux/irq.h>
Yuan Yaof1cd8c82014-02-17 13:28:07 +080019#include <linux/module.h>
Jingchang Luc9e2e942013-06-07 09:20:40 +080020#include <linux/of.h>
21#include <linux/of_device.h>
Yuan Yaof1cd8c82014-02-17 13:28:07 +080022#include <linux/of_dma.h>
Jingchang Luc9e2e942013-06-07 09:20:40 +080023#include <linux/serial_core.h>
Yuan Yaof1cd8c82014-02-17 13:28:07 +080024#include <linux/slab.h>
Jingchang Luc9e2e942013-06-07 09:20:40 +080025#include <linux/tty_flip.h>
26
27/* All registers are 8-bit width */
28#define UARTBDH 0x00
29#define UARTBDL 0x01
30#define UARTCR1 0x02
31#define UARTCR2 0x03
32#define UARTSR1 0x04
33#define UARTCR3 0x06
34#define UARTDR 0x07
35#define UARTCR4 0x0a
36#define UARTCR5 0x0b
37#define UARTMODEM 0x0d
38#define UARTPFIFO 0x10
39#define UARTCFIFO 0x11
40#define UARTSFIFO 0x12
41#define UARTTWFIFO 0x13
42#define UARTTCFIFO 0x14
43#define UARTRWFIFO 0x15
44
45#define UARTBDH_LBKDIE 0x80
46#define UARTBDH_RXEDGIE 0x40
47#define UARTBDH_SBR_MASK 0x1f
48
49#define UARTCR1_LOOPS 0x80
50#define UARTCR1_RSRC 0x20
51#define UARTCR1_M 0x10
52#define UARTCR1_WAKE 0x08
53#define UARTCR1_ILT 0x04
54#define UARTCR1_PE 0x02
55#define UARTCR1_PT 0x01
56
57#define UARTCR2_TIE 0x80
58#define UARTCR2_TCIE 0x40
59#define UARTCR2_RIE 0x20
60#define UARTCR2_ILIE 0x10
61#define UARTCR2_TE 0x08
62#define UARTCR2_RE 0x04
63#define UARTCR2_RWU 0x02
64#define UARTCR2_SBK 0x01
65
66#define UARTSR1_TDRE 0x80
67#define UARTSR1_TC 0x40
68#define UARTSR1_RDRF 0x20
69#define UARTSR1_IDLE 0x10
70#define UARTSR1_OR 0x08
71#define UARTSR1_NF 0x04
72#define UARTSR1_FE 0x02
73#define UARTSR1_PE 0x01
74
75#define UARTCR3_R8 0x80
76#define UARTCR3_T8 0x40
77#define UARTCR3_TXDIR 0x20
78#define UARTCR3_TXINV 0x10
79#define UARTCR3_ORIE 0x08
80#define UARTCR3_NEIE 0x04
81#define UARTCR3_FEIE 0x02
82#define UARTCR3_PEIE 0x01
83
84#define UARTCR4_MAEN1 0x80
85#define UARTCR4_MAEN2 0x40
86#define UARTCR4_M10 0x20
87#define UARTCR4_BRFA_MASK 0x1f
88#define UARTCR4_BRFA_OFF 0
89
90#define UARTCR5_TDMAS 0x80
91#define UARTCR5_RDMAS 0x20
92
93#define UARTMODEM_RXRTSE 0x08
94#define UARTMODEM_TXRTSPOL 0x04
95#define UARTMODEM_TXRTSE 0x02
96#define UARTMODEM_TXCTSE 0x01
97
98#define UARTPFIFO_TXFE 0x80
99#define UARTPFIFO_FIFOSIZE_MASK 0x7
100#define UARTPFIFO_TXSIZE_OFF 4
101#define UARTPFIFO_RXFE 0x08
102#define UARTPFIFO_RXSIZE_OFF 0
103
104#define UARTCFIFO_TXFLUSH 0x80
105#define UARTCFIFO_RXFLUSH 0x40
106#define UARTCFIFO_RXOFE 0x04
107#define UARTCFIFO_TXOFE 0x02
108#define UARTCFIFO_RXUFE 0x01
109
110#define UARTSFIFO_TXEMPT 0x80
111#define UARTSFIFO_RXEMPT 0x40
112#define UARTSFIFO_RXOF 0x04
113#define UARTSFIFO_TXOF 0x02
114#define UARTSFIFO_RXUF 0x01
115
Marius Vlada5fa2662017-07-16 01:00:58 +0300116/* 32-bit register definition */
Jingchang Lu380c9662014-07-14 17:41:11 +0800117#define UARTBAUD 0x00
118#define UARTSTAT 0x04
119#define UARTCTRL 0x08
120#define UARTDATA 0x0C
121#define UARTMATCH 0x10
122#define UARTMODIR 0x14
123#define UARTFIFO 0x18
124#define UARTWATER 0x1c
125
126#define UARTBAUD_MAEN1 0x80000000
127#define UARTBAUD_MAEN2 0x40000000
128#define UARTBAUD_M10 0x20000000
129#define UARTBAUD_TDMAE 0x00800000
130#define UARTBAUD_RDMAE 0x00200000
131#define UARTBAUD_MATCFG 0x00400000
132#define UARTBAUD_BOTHEDGE 0x00020000
133#define UARTBAUD_RESYNCDIS 0x00010000
134#define UARTBAUD_LBKDIE 0x00008000
135#define UARTBAUD_RXEDGIE 0x00004000
136#define UARTBAUD_SBNS 0x00002000
137#define UARTBAUD_SBR 0x00000000
138#define UARTBAUD_SBR_MASK 0x1fff
Dong Aishenga6d75142017-06-13 10:55:54 +0800139#define UARTBAUD_OSR_MASK 0x1f
140#define UARTBAUD_OSR_SHIFT 24
Jingchang Lu380c9662014-07-14 17:41:11 +0800141
142#define UARTSTAT_LBKDIF 0x80000000
143#define UARTSTAT_RXEDGIF 0x40000000
144#define UARTSTAT_MSBF 0x20000000
145#define UARTSTAT_RXINV 0x10000000
146#define UARTSTAT_RWUID 0x08000000
147#define UARTSTAT_BRK13 0x04000000
148#define UARTSTAT_LBKDE 0x02000000
149#define UARTSTAT_RAF 0x01000000
150#define UARTSTAT_TDRE 0x00800000
151#define UARTSTAT_TC 0x00400000
152#define UARTSTAT_RDRF 0x00200000
153#define UARTSTAT_IDLE 0x00100000
154#define UARTSTAT_OR 0x00080000
155#define UARTSTAT_NF 0x00040000
156#define UARTSTAT_FE 0x00020000
157#define UARTSTAT_PE 0x00010000
158#define UARTSTAT_MA1F 0x00008000
159#define UARTSTAT_M21F 0x00004000
160
161#define UARTCTRL_R8T9 0x80000000
162#define UARTCTRL_R9T8 0x40000000
163#define UARTCTRL_TXDIR 0x20000000
164#define UARTCTRL_TXINV 0x10000000
165#define UARTCTRL_ORIE 0x08000000
166#define UARTCTRL_NEIE 0x04000000
167#define UARTCTRL_FEIE 0x02000000
168#define UARTCTRL_PEIE 0x01000000
169#define UARTCTRL_TIE 0x00800000
170#define UARTCTRL_TCIE 0x00400000
171#define UARTCTRL_RIE 0x00200000
172#define UARTCTRL_ILIE 0x00100000
173#define UARTCTRL_TE 0x00080000
174#define UARTCTRL_RE 0x00040000
175#define UARTCTRL_RWU 0x00020000
176#define UARTCTRL_SBK 0x00010000
177#define UARTCTRL_MA1IE 0x00008000
178#define UARTCTRL_MA2IE 0x00004000
179#define UARTCTRL_IDLECFG 0x00000100
180#define UARTCTRL_LOOPS 0x00000080
181#define UARTCTRL_DOZEEN 0x00000040
182#define UARTCTRL_RSRC 0x00000020
183#define UARTCTRL_M 0x00000010
184#define UARTCTRL_WAKE 0x00000008
185#define UARTCTRL_ILT 0x00000004
186#define UARTCTRL_PE 0x00000002
187#define UARTCTRL_PT 0x00000001
188
189#define UARTDATA_NOISY 0x00008000
190#define UARTDATA_PARITYE 0x00004000
191#define UARTDATA_FRETSC 0x00002000
192#define UARTDATA_RXEMPT 0x00001000
193#define UARTDATA_IDLINE 0x00000800
194#define UARTDATA_MASK 0x3ff
195
196#define UARTMODIR_IREN 0x00020000
197#define UARTMODIR_TXCTSSRC 0x00000020
198#define UARTMODIR_TXCTSC 0x00000010
199#define UARTMODIR_RXRTSE 0x00000008
200#define UARTMODIR_TXRTSPOL 0x00000004
201#define UARTMODIR_TXRTSE 0x00000002
202#define UARTMODIR_TXCTSE 0x00000001
203
204#define UARTFIFO_TXEMPT 0x00800000
205#define UARTFIFO_RXEMPT 0x00400000
206#define UARTFIFO_TXOF 0x00020000
207#define UARTFIFO_RXUF 0x00010000
208#define UARTFIFO_TXFLUSH 0x00008000
209#define UARTFIFO_RXFLUSH 0x00004000
210#define UARTFIFO_TXOFE 0x00000200
211#define UARTFIFO_RXUFE 0x00000100
212#define UARTFIFO_TXFE 0x00000080
213#define UARTFIFO_FIFOSIZE_MASK 0x7
214#define UARTFIFO_TXSIZE_OFF 4
215#define UARTFIFO_RXFE 0x00000008
216#define UARTFIFO_RXSIZE_OFF 0
Fugang Duanf77ebb22019-07-17 13:19:30 +0800217#define UARTFIFO_DEPTH(x) (0x1 << ((x) ? ((x) + 1) : 0))
Jingchang Lu380c9662014-07-14 17:41:11 +0800218
219#define UARTWATER_COUNT_MASK 0xff
220#define UARTWATER_TXCNT_OFF 8
221#define UARTWATER_RXCNT_OFF 24
222#define UARTWATER_WATER_MASK 0xff
223#define UARTWATER_TXWATER_OFF 0
224#define UARTWATER_RXWATER_OFF 16
225
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530226/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
227#define DMA_RX_TIMEOUT (10)
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800228
Jingchang Luc9e2e942013-06-07 09:20:40 +0800229#define DRIVER_NAME "fsl-lpuart"
230#define DEV_NAME "ttyLP"
231#define UART_NR 6
232
Dong Aisheng24b1e5f2017-06-13 10:55:52 +0800233/* IMX lpuart has four extra unused regs located at the beginning */
234#define IMX_REG_OFF 0x10
235
Vabhav Sharma3bc32062018-10-10 03:56:16 +0530236static DEFINE_IDA(fsl_lpuart_ida);
237
Fugang Duan35a4ed02019-07-04 21:40:07 +0800238enum lpuart_type {
239 VF610_LPUART,
240 LS1021A_LPUART,
241 IMX7ULP_LPUART,
242 IMX8QXP_LPUART,
243};
244
Jingchang Luc9e2e942013-06-07 09:20:40 +0800245struct lpuart_port {
246 struct uart_port port;
Fugang Duan35a4ed02019-07-04 21:40:07 +0800247 enum lpuart_type devtype;
248 struct clk *ipg_clk;
249 struct clk *baud_clk;
Jingchang Luc9e2e942013-06-07 09:20:40 +0800250 unsigned int txfifo_size;
251 unsigned int rxfifo_size;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800252
Stefan Agner4a818c42015-01-10 09:33:45 +0100253 bool lpuart_dma_tx_use;
254 bool lpuart_dma_rx_use;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800255 struct dma_chan *dma_tx_chan;
256 struct dma_chan *dma_rx_chan;
257 struct dma_async_tx_descriptor *dma_tx_desc;
258 struct dma_async_tx_descriptor *dma_rx_desc;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800259 dma_cookie_t dma_tx_cookie;
260 dma_cookie_t dma_rx_cookie;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800261 unsigned int dma_tx_bytes;
262 unsigned int dma_rx_bytes;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530263 bool dma_tx_in_progress;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800264 unsigned int dma_rx_timeout;
265 struct timer_list lpuart_timer;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530266 struct scatterlist rx_sgl, tx_sgl[2];
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530267 struct circ_buf rx_ring;
268 int rx_dma_rng_buf_len;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530269 unsigned int dma_tx_nents;
270 wait_queue_head_t dma_wait;
Jingchang Luc9e2e942013-06-07 09:20:40 +0800271};
272
Dong Aisheng0d6fce92017-06-13 10:55:48 +0800273struct lpuart_soc_data {
Fugang Duan35a4ed02019-07-04 21:40:07 +0800274 enum lpuart_type devtype;
275 char iotype;
276 u8 reg_off;
Dong Aisheng0d6fce92017-06-13 10:55:48 +0800277};
278
279static const struct lpuart_soc_data vf_data = {
Fugang Duan35a4ed02019-07-04 21:40:07 +0800280 .devtype = VF610_LPUART,
Dong Aisheng0d6fce92017-06-13 10:55:48 +0800281 .iotype = UPIO_MEM,
282};
283
284static const struct lpuart_soc_data ls_data = {
Fugang Duan35a4ed02019-07-04 21:40:07 +0800285 .devtype = LS1021A_LPUART,
Dong Aisheng0d6fce92017-06-13 10:55:48 +0800286 .iotype = UPIO_MEM32BE,
287};
288
Fugang Duan35a4ed02019-07-04 21:40:07 +0800289static struct lpuart_soc_data imx7ulp_data = {
290 .devtype = IMX7ULP_LPUART,
291 .iotype = UPIO_MEM32,
292 .reg_off = IMX_REG_OFF,
293};
294
295static struct lpuart_soc_data imx8qxp_data = {
296 .devtype = IMX8QXP_LPUART,
Dong Aisheng24b1e5f2017-06-13 10:55:52 +0800297 .iotype = UPIO_MEM32,
298 .reg_off = IMX_REG_OFF,
299};
300
Fabian Fredericked0bb232015-03-16 20:17:11 +0100301static const struct of_device_id lpuart_dt_ids[] = {
Dong Aisheng0d6fce92017-06-13 10:55:48 +0800302 { .compatible = "fsl,vf610-lpuart", .data = &vf_data, },
303 { .compatible = "fsl,ls1021a-lpuart", .data = &ls_data, },
Fugang Duan35a4ed02019-07-04 21:40:07 +0800304 { .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, },
305 { .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, },
Jingchang Luc9e2e942013-06-07 09:20:40 +0800306 { /* sentinel */ }
307};
308MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
309
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800310/* Forward declare this for the dma callbacks*/
311static void lpuart_dma_tx_complete(void *arg);
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800312
Fugang Duan35a4ed02019-07-04 21:40:07 +0800313static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
314{
315 return sport->devtype == IMX8QXP_LPUART;
316}
317
Dong Aishengf98e1fc2017-06-13 10:55:50 +0800318static inline u32 lpuart32_read(struct uart_port *port, u32 off)
Jingchang Lu380c9662014-07-14 17:41:11 +0800319{
Dong Aishengf98e1fc2017-06-13 10:55:50 +0800320 switch (port->iotype) {
321 case UPIO_MEM32:
322 return readl(port->membase + off);
323 case UPIO_MEM32BE:
324 return ioread32be(port->membase + off);
325 default:
326 return 0;
327 }
Jingchang Lu380c9662014-07-14 17:41:11 +0800328}
329
Dong Aishenga0204f22017-06-13 10:55:49 +0800330static inline void lpuart32_write(struct uart_port *port, u32 val,
Dong Aishengf98e1fc2017-06-13 10:55:50 +0800331 u32 off)
Jingchang Lu380c9662014-07-14 17:41:11 +0800332{
Dong Aishengf98e1fc2017-06-13 10:55:50 +0800333 switch (port->iotype) {
334 case UPIO_MEM32:
335 writel(val, port->membase + off);
336 break;
337 case UPIO_MEM32BE:
338 iowrite32be(val, port->membase + off);
339 break;
340 }
Jingchang Lu380c9662014-07-14 17:41:11 +0800341}
342
Fugang Duan35a4ed02019-07-04 21:40:07 +0800343static int __lpuart_enable_clks(struct lpuart_port *sport, bool is_en)
344{
345 int ret = 0;
346
347 if (is_en) {
348 ret = clk_prepare_enable(sport->ipg_clk);
349 if (ret)
350 return ret;
351
352 ret = clk_prepare_enable(sport->baud_clk);
353 if (ret) {
354 clk_disable_unprepare(sport->ipg_clk);
355 return ret;
356 }
357 } else {
358 clk_disable_unprepare(sport->baud_clk);
359 clk_disable_unprepare(sport->ipg_clk);
360 }
361
362 return 0;
363}
364
365static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport)
366{
367 if (is_imx8qxp_lpuart(sport))
368 return clk_get_rate(sport->baud_clk);
369
370 return clk_get_rate(sport->ipg_clk);
371}
372
373#define lpuart_enable_clks(x) __lpuart_enable_clks(x, true)
374#define lpuart_disable_clks(x) __lpuart_enable_clks(x, false)
375
Jingchang Luc9e2e942013-06-07 09:20:40 +0800376static void lpuart_stop_tx(struct uart_port *port)
377{
378 unsigned char temp;
379
380 temp = readb(port->membase + UARTCR2);
381 temp &= ~(UARTCR2_TIE | UARTCR2_TCIE);
382 writeb(temp, port->membase + UARTCR2);
383}
384
Jingchang Lu380c9662014-07-14 17:41:11 +0800385static void lpuart32_stop_tx(struct uart_port *port)
386{
387 unsigned long temp;
388
Dong Aishenga0204f22017-06-13 10:55:49 +0800389 temp = lpuart32_read(port, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +0800390 temp &= ~(UARTCTRL_TIE | UARTCTRL_TCIE);
Dong Aishenga0204f22017-06-13 10:55:49 +0800391 lpuart32_write(port, temp, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +0800392}
393
Jingchang Luc9e2e942013-06-07 09:20:40 +0800394static void lpuart_stop_rx(struct uart_port *port)
395{
396 unsigned char temp;
397
398 temp = readb(port->membase + UARTCR2);
399 writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2);
400}
401
Jingchang Lu380c9662014-07-14 17:41:11 +0800402static void lpuart32_stop_rx(struct uart_port *port)
403{
404 unsigned long temp;
405
Dong Aishenga0204f22017-06-13 10:55:49 +0800406 temp = lpuart32_read(port, UARTCTRL);
407 lpuart32_write(port, temp & ~UARTCTRL_RE, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +0800408}
409
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530410static void lpuart_dma_tx(struct lpuart_port *sport)
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800411{
412 struct circ_buf *xmit = &sport->port.state->xmit;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530413 struct scatterlist *sgl = sport->tx_sgl;
414 struct device *dev = sport->port.dev;
415 int ret;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800416
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530417 if (sport->dma_tx_in_progress)
418 return;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800419
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530420 sport->dma_tx_bytes = uart_circ_chars_pending(xmit);
421
Aaron Briced704b2d2016-10-06 15:13:04 -0700422 if (xmit->tail < xmit->head || xmit->head == 0) {
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530423 sport->dma_tx_nents = 1;
424 sg_init_one(sgl, xmit->buf + xmit->tail, sport->dma_tx_bytes);
425 } else {
426 sport->dma_tx_nents = 2;
427 sg_init_table(sgl, 2);
428 sg_set_buf(sgl, xmit->buf + xmit->tail,
429 UART_XMIT_SIZE - xmit->tail);
430 sg_set_buf(sgl + 1, xmit->buf, xmit->head);
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800431 }
432
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530433 ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
434 if (!ret) {
435 dev_err(dev, "DMA mapping error for TX.\n");
436 return;
437 }
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800438
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530439 sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl,
440 sport->dma_tx_nents,
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800441 DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800442 if (!sport->dma_tx_desc) {
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530443 dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
444 dev_err(dev, "Cannot prepare TX slave DMA!\n");
445 return;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800446 }
447
448 sport->dma_tx_desc->callback = lpuart_dma_tx_complete;
449 sport->dma_tx_desc->callback_param = sport;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530450 sport->dma_tx_in_progress = true;
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800451 sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
452 dma_async_issue_pending(sport->dma_tx_chan);
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800453}
454
455static void lpuart_dma_tx_complete(void *arg)
456{
457 struct lpuart_port *sport = arg;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530458 struct scatterlist *sgl = &sport->tx_sgl[0];
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800459 struct circ_buf *xmit = &sport->port.state->xmit;
460 unsigned long flags;
461
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800462 spin_lock_irqsave(&sport->port.lock, flags);
463
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530464 dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
465
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800466 xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1);
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530467
468 sport->port.icount.tx += sport->dma_tx_bytes;
469 sport->dma_tx_in_progress = false;
470 spin_unlock_irqrestore(&sport->port.lock, flags);
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800471
472 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
473 uart_write_wakeup(&sport->port);
474
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530475 if (waitqueue_active(&sport->dma_wait)) {
476 wake_up(&sport->dma_wait);
477 return;
478 }
479
480 spin_lock_irqsave(&sport->port.lock, flags);
481
482 if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port))
483 lpuart_dma_tx(sport);
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800484
485 spin_unlock_irqrestore(&sport->port.lock, flags);
486}
487
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900488static dma_addr_t lpuart_dma_datareg_addr(struct lpuart_port *sport)
489{
490 switch (sport->port.iotype) {
491 case UPIO_MEM32:
492 return sport->port.mapbase + UARTDATA;
493 case UPIO_MEM32BE:
494 return sport->port.mapbase + UARTDATA + sizeof(u32) - 1;
495 }
496 return sport->port.mapbase + UARTDR;
497}
498
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530499static int lpuart_dma_tx_request(struct uart_port *port)
500{
501 struct lpuart_port *sport = container_of(port,
502 struct lpuart_port, port);
503 struct dma_slave_config dma_tx_sconfig = {};
504 int ret;
505
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900506 dma_tx_sconfig.dst_addr = lpuart_dma_datareg_addr(sport);
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530507 dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
508 dma_tx_sconfig.dst_maxburst = 1;
509 dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
510 ret = dmaengine_slave_config(sport->dma_tx_chan, &dma_tx_sconfig);
511
512 if (ret) {
513 dev_err(sport->port.dev,
514 "DMA slave config failed, err = %d\n", ret);
515 return ret;
516 }
517
518 return 0;
519}
520
Andrey Smirnov9bc19af2019-07-29 12:52:05 -0700521static bool lpuart_is_32(struct lpuart_port *sport)
522{
523 return sport->port.iotype == UPIO_MEM32 ||
524 sport->port.iotype == UPIO_MEM32BE;
525}
526
Stefan Agnerbfc2e072015-01-26 01:10:16 +0100527static void lpuart_flush_buffer(struct uart_port *port)
528{
529 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
Andrey Smirnov9bc19af2019-07-29 12:52:05 -0700530 u32 val;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530531
Stefan Agnerbfc2e072015-01-26 01:10:16 +0100532 if (sport->lpuart_dma_tx_use) {
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530533 if (sport->dma_tx_in_progress) {
534 dma_unmap_sg(sport->port.dev, &sport->tx_sgl[0],
535 sport->dma_tx_nents, DMA_TO_DEVICE);
536 sport->dma_tx_in_progress = false;
537 }
Stefan Agnerbfc2e072015-01-26 01:10:16 +0100538 dmaengine_terminate_all(sport->dma_tx_chan);
Stefan Agnerbfc2e072015-01-26 01:10:16 +0100539 }
Andrey Smirnov9bc19af2019-07-29 12:52:05 -0700540
541 if (lpuart_is_32(sport)) {
542 val = lpuart32_read(&sport->port, UARTFIFO);
543 val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
544 lpuart32_write(&sport->port, val, UARTFIFO);
545 } else {
546 val = readb(sport->port.membase + UARTPFIFO);
547 val |= UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH;
548 writeb(val, sport->port.membase + UARTCFIFO);
549 }
Stefan Agnerbfc2e072015-01-26 01:10:16 +0100550}
551
Nicolae Rosia2a41bc22016-10-04 15:46:16 +0300552#if defined(CONFIG_CONSOLE_POLL)
553
554static int lpuart_poll_init(struct uart_port *port)
555{
556 struct lpuart_port *sport = container_of(port,
557 struct lpuart_port, port);
558 unsigned long flags;
559 unsigned char temp;
560
561 sport->port.fifosize = 0;
562
563 spin_lock_irqsave(&sport->port.lock, flags);
564 /* Disable Rx & Tx */
565 writeb(0, sport->port.membase + UARTCR2);
566
567 temp = readb(sport->port.membase + UARTPFIFO);
568 /* Enable Rx and Tx FIFO */
569 writeb(temp | UARTPFIFO_RXFE | UARTPFIFO_TXFE,
570 sport->port.membase + UARTPFIFO);
571
572 /* flush Tx and Rx FIFO */
573 writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
574 sport->port.membase + UARTCFIFO);
575
576 /* explicitly clear RDRF */
577 if (readb(sport->port.membase + UARTSR1) & UARTSR1_RDRF) {
578 readb(sport->port.membase + UARTDR);
579 writeb(UARTSFIFO_RXUF, sport->port.membase + UARTSFIFO);
580 }
581
582 writeb(0, sport->port.membase + UARTTWFIFO);
583 writeb(1, sport->port.membase + UARTRWFIFO);
584
585 /* Enable Rx and Tx */
586 writeb(UARTCR2_RE | UARTCR2_TE, sport->port.membase + UARTCR2);
587 spin_unlock_irqrestore(&sport->port.lock, flags);
588
589 return 0;
590}
591
592static void lpuart_poll_put_char(struct uart_port *port, unsigned char c)
593{
Nicolae Rosia2a41bc22016-10-04 15:46:16 +0300594 /* drain */
595 while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE))
596 barrier();
597
598 writeb(c, port->membase + UARTDR);
599}
600
601static int lpuart_poll_get_char(struct uart_port *port)
602{
603 if (!(readb(port->membase + UARTSR1) & UARTSR1_RDRF))
604 return NO_POLL_CHAR;
605
606 return readb(port->membase + UARTDR);
607}
608
Marius Vlada5fa2662017-07-16 01:00:58 +0300609static int lpuart32_poll_init(struct uart_port *port)
610{
611 unsigned long flags;
612 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
613 u32 temp;
614
615 sport->port.fifosize = 0;
616
617 spin_lock_irqsave(&sport->port.lock, flags);
618
619 /* Disable Rx & Tx */
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700620 lpuart32_write(&sport->port, UARTCTRL, 0);
Marius Vlada5fa2662017-07-16 01:00:58 +0300621
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700622 temp = lpuart32_read(&sport->port, UARTFIFO);
Marius Vlada5fa2662017-07-16 01:00:58 +0300623
624 /* Enable Rx and Tx FIFO */
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700625 lpuart32_write(&sport->port, UARTFIFO,
626 temp | UARTFIFO_RXFE | UARTFIFO_TXFE);
Marius Vlada5fa2662017-07-16 01:00:58 +0300627
628 /* flush Tx and Rx FIFO */
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700629 lpuart32_write(&sport->port, UARTFIFO,
630 UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH);
Marius Vlada5fa2662017-07-16 01:00:58 +0300631
632 /* explicitly clear RDRF */
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700633 if (lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_RDRF) {
634 lpuart32_read(&sport->port, UARTDATA);
635 lpuart32_write(&sport->port, UARTFIFO, UARTFIFO_RXUF);
Marius Vlada5fa2662017-07-16 01:00:58 +0300636 }
637
638 /* Enable Rx and Tx */
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700639 lpuart32_write(&sport->port, UARTCTRL, UARTCTRL_RE | UARTCTRL_TE);
Marius Vlada5fa2662017-07-16 01:00:58 +0300640 spin_unlock_irqrestore(&sport->port.lock, flags);
641
642 return 0;
643}
644
645static void lpuart32_poll_put_char(struct uart_port *port, unsigned char c)
646{
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700647 while (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE))
Marius Vlada5fa2662017-07-16 01:00:58 +0300648 barrier();
649
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700650 lpuart32_write(port, UARTDATA, c);
Marius Vlada5fa2662017-07-16 01:00:58 +0300651}
652
653static int lpuart32_poll_get_char(struct uart_port *port)
654{
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700655 if (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_RDRF))
Marius Vlada5fa2662017-07-16 01:00:58 +0300656 return NO_POLL_CHAR;
657
Andrey Smirnov1da17d72019-07-29 12:52:15 -0700658 return lpuart32_read(port, UARTDATA);
Marius Vlada5fa2662017-07-16 01:00:58 +0300659}
Nicolae Rosia2a41bc22016-10-04 15:46:16 +0300660#endif
661
Jingchang Luc9e2e942013-06-07 09:20:40 +0800662static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
663{
664 struct circ_buf *xmit = &sport->port.state->xmit;
665
Andrey Smirnov93b95232019-07-29 12:52:11 -0700666 if (sport->port.x_char) {
667 writeb(sport->port.x_char, sport->port.membase + UARTDR);
668 sport->port.icount.tx++;
669 sport->port.x_char = 0;
670 return;
671 }
672
673 if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
674 lpuart_stop_tx(&sport->port);
675 return;
676 }
677
Jingchang Luc9e2e942013-06-07 09:20:40 +0800678 while (!uart_circ_empty(xmit) &&
679 (readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size)) {
680 writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR);
681 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
682 sport->port.icount.tx++;
683 }
684
685 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
686 uart_write_wakeup(&sport->port);
687
688 if (uart_circ_empty(xmit))
689 lpuart_stop_tx(&sport->port);
690}
691
Jingchang Lu380c9662014-07-14 17:41:11 +0800692static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
693{
694 struct circ_buf *xmit = &sport->port.state->xmit;
695 unsigned long txcnt;
696
Andrey Smirnov93b95232019-07-29 12:52:11 -0700697 if (sport->port.x_char) {
698 lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
699 sport->port.icount.tx++;
700 sport->port.x_char = 0;
701 return;
702 }
703
704 if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
705 lpuart32_stop_tx(&sport->port);
706 return;
707 }
708
Dong Aishenga0204f22017-06-13 10:55:49 +0800709 txcnt = lpuart32_read(&sport->port, UARTWATER);
Jingchang Lu380c9662014-07-14 17:41:11 +0800710 txcnt = txcnt >> UARTWATER_TXCNT_OFF;
711 txcnt &= UARTWATER_COUNT_MASK;
712 while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) {
Dong Aishenga0204f22017-06-13 10:55:49 +0800713 lpuart32_write(&sport->port, xmit->buf[xmit->tail], UARTDATA);
Jingchang Lu380c9662014-07-14 17:41:11 +0800714 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
715 sport->port.icount.tx++;
Dong Aishenga0204f22017-06-13 10:55:49 +0800716 txcnt = lpuart32_read(&sport->port, UARTWATER);
Jingchang Lu380c9662014-07-14 17:41:11 +0800717 txcnt = txcnt >> UARTWATER_TXCNT_OFF;
718 txcnt &= UARTWATER_COUNT_MASK;
719 }
720
721 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
722 uart_write_wakeup(&sport->port);
723
724 if (uart_circ_empty(xmit))
725 lpuart32_stop_tx(&sport->port);
726}
727
Jingchang Luc9e2e942013-06-07 09:20:40 +0800728static void lpuart_start_tx(struct uart_port *port)
729{
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800730 struct lpuart_port *sport = container_of(port,
731 struct lpuart_port, port);
732 struct circ_buf *xmit = &sport->port.state->xmit;
Jingchang Luc9e2e942013-06-07 09:20:40 +0800733 unsigned char temp;
734
735 temp = readb(port->membase + UARTCR2);
736 writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
737
Stefan Agner4a818c42015-01-10 09:33:45 +0100738 if (sport->lpuart_dma_tx_use) {
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530739 if (!uart_circ_empty(xmit) && !uart_tx_stopped(port))
740 lpuart_dma_tx(sport);
Yuan Yaof1cd8c82014-02-17 13:28:07 +0800741 } else {
742 if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
743 lpuart_transmit_buffer(sport);
744 }
Jingchang Luc9e2e942013-06-07 09:20:40 +0800745}
746
Jingchang Lu380c9662014-07-14 17:41:11 +0800747static void lpuart32_start_tx(struct uart_port *port)
748{
749 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900750 struct circ_buf *xmit = &sport->port.state->xmit;
Jingchang Lu380c9662014-07-14 17:41:11 +0800751 unsigned long temp;
752
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900753 if (sport->lpuart_dma_tx_use) {
754 if (!uart_circ_empty(xmit) && !uart_tx_stopped(port))
755 lpuart_dma_tx(sport);
756 } else {
757 temp = lpuart32_read(port, UARTCTRL);
758 lpuart32_write(port, temp | UARTCTRL_TIE, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +0800759
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900760 if (lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE)
761 lpuart32_transmit_buffer(sport);
762 }
Jingchang Lu380c9662014-07-14 17:41:11 +0800763}
764
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530765/* return TIOCSER_TEMT when transmitter is not busy */
766static unsigned int lpuart_tx_empty(struct uart_port *port)
767{
768 struct lpuart_port *sport = container_of(port,
769 struct lpuart_port, port);
770 unsigned char sr1 = readb(port->membase + UARTSR1);
771 unsigned char sfifo = readb(port->membase + UARTSFIFO);
772
773 if (sport->dma_tx_in_progress)
774 return 0;
775
776 if (sr1 & UARTSR1_TC && sfifo & UARTSFIFO_TXEMPT)
777 return TIOCSER_TEMT;
778
779 return 0;
780}
781
782static unsigned int lpuart32_tx_empty(struct uart_port *port)
783{
Atsushi Nemoto46dd6d72019-01-21 17:37:28 +0900784 struct lpuart_port *sport = container_of(port,
785 struct lpuart_port, port);
786 unsigned long stat = lpuart32_read(port, UARTSTAT);
787 unsigned long sfifo = lpuart32_read(port, UARTFIFO);
788
789 if (sport->dma_tx_in_progress)
790 return 0;
791
792 if (stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT)
793 return TIOCSER_TEMT;
794
795 return 0;
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530796}
797
Andrey Smirnov3993ddc2019-07-29 12:52:06 -0700798static void lpuart_txint(struct lpuart_port *sport)
Jingchang Luc9e2e942013-06-07 09:20:40 +0800799{
Jingchang Luc9e2e942013-06-07 09:20:40 +0800800 unsigned long flags;
801
802 spin_lock_irqsave(&sport->port.lock, flags);
Andrey Smirnov93b95232019-07-29 12:52:11 -0700803 lpuart_transmit_buffer(sport);
Jingchang Luc9e2e942013-06-07 09:20:40 +0800804 spin_unlock_irqrestore(&sport->port.lock, flags);
Jingchang Luc9e2e942013-06-07 09:20:40 +0800805}
806
Andrey Smirnov3993ddc2019-07-29 12:52:06 -0700807static void lpuart_rxint(struct lpuart_port *sport)
Jingchang Luc9e2e942013-06-07 09:20:40 +0800808{
Stefan Agnercc584ab2019-07-29 12:52:04 -0700809 unsigned int flg, ignored = 0, overrun = 0;
Jingchang Luc9e2e942013-06-07 09:20:40 +0800810 struct tty_port *port = &sport->port.state->port;
811 unsigned long flags;
812 unsigned char rx, sr;
813
814 spin_lock_irqsave(&sport->port.lock, flags);
815
816 while (!(readb(sport->port.membase + UARTSFIFO) & UARTSFIFO_RXEMPT)) {
817 flg = TTY_NORMAL;
818 sport->port.icount.rx++;
819 /*
820 * to clear the FE, OR, NF, FE, PE flags,
821 * read SR1 then read DR
822 */
823 sr = readb(sport->port.membase + UARTSR1);
824 rx = readb(sport->port.membase + UARTDR);
825
826 if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
827 continue;
828
829 if (sr & (UARTSR1_PE | UARTSR1_OR | UARTSR1_FE)) {
830 if (sr & UARTSR1_PE)
831 sport->port.icount.parity++;
832 else if (sr & UARTSR1_FE)
833 sport->port.icount.frame++;
834
835 if (sr & UARTSR1_OR)
Stefan Agnercc584ab2019-07-29 12:52:04 -0700836 overrun++;
Jingchang Luc9e2e942013-06-07 09:20:40 +0800837
838 if (sr & sport->port.ignore_status_mask) {
839 if (++ignored > 100)
840 goto out;
841 continue;
842 }
843
844 sr &= sport->port.read_status_mask;
845
846 if (sr & UARTSR1_PE)
847 flg = TTY_PARITY;
848 else if (sr & UARTSR1_FE)
849 flg = TTY_FRAME;
850
851 if (sr & UARTSR1_OR)
852 flg = TTY_OVERRUN;
853
854#ifdef SUPPORT_SYSRQ
855 sport->port.sysrq = 0;
856#endif
857 }
858
859 tty_insert_flip_char(port, rx, flg);
860 }
861
862out:
Stefan Agnercc584ab2019-07-29 12:52:04 -0700863 if (overrun) {
864 sport->port.icount.overrun += overrun;
865
866 /*
867 * Overruns cause FIFO pointers to become missaligned.
868 * Flushing the receive FIFO reinitializes the pointers.
869 */
870 writeb(UARTCFIFO_RXFLUSH, sport->port.membase + UARTCFIFO);
871 writeb(UARTSFIFO_RXOF, sport->port.membase + UARTSFIFO);
872 }
873
Jingchang Luc9e2e942013-06-07 09:20:40 +0800874 spin_unlock_irqrestore(&sport->port.lock, flags);
875
876 tty_flip_buffer_push(port);
Jingchang Luc9e2e942013-06-07 09:20:40 +0800877}
878
Andrey Smirnov93b95232019-07-29 12:52:11 -0700879static void lpuart32_txint(struct lpuart_port *sport)
880{
881 unsigned long flags;
882
883 spin_lock_irqsave(&sport->port.lock, flags);
884 lpuart32_transmit_buffer(sport);
885 spin_unlock_irqrestore(&sport->port.lock, flags);
886}
887
Andrey Smirnov3993ddc2019-07-29 12:52:06 -0700888static void lpuart32_rxint(struct lpuart_port *sport)
Jingchang Lu380c9662014-07-14 17:41:11 +0800889{
Jingchang Lu380c9662014-07-14 17:41:11 +0800890 unsigned int flg, ignored = 0;
891 struct tty_port *port = &sport->port.state->port;
892 unsigned long flags;
893 unsigned long rx, sr;
894
895 spin_lock_irqsave(&sport->port.lock, flags);
896
Dong Aishenga0204f22017-06-13 10:55:49 +0800897 while (!(lpuart32_read(&sport->port, UARTFIFO) & UARTFIFO_RXEMPT)) {
Jingchang Lu380c9662014-07-14 17:41:11 +0800898 flg = TTY_NORMAL;
899 sport->port.icount.rx++;
900 /*
901 * to clear the FE, OR, NF, FE, PE flags,
902 * read STAT then read DATA reg
903 */
Dong Aishenga0204f22017-06-13 10:55:49 +0800904 sr = lpuart32_read(&sport->port, UARTSTAT);
905 rx = lpuart32_read(&sport->port, UARTDATA);
Jingchang Lu380c9662014-07-14 17:41:11 +0800906 rx &= 0x3ff;
907
908 if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
909 continue;
910
911 if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) {
912 if (sr & UARTSTAT_PE)
913 sport->port.icount.parity++;
914 else if (sr & UARTSTAT_FE)
915 sport->port.icount.frame++;
916
917 if (sr & UARTSTAT_OR)
918 sport->port.icount.overrun++;
919
920 if (sr & sport->port.ignore_status_mask) {
921 if (++ignored > 100)
922 goto out;
923 continue;
924 }
925
926 sr &= sport->port.read_status_mask;
927
928 if (sr & UARTSTAT_PE)
929 flg = TTY_PARITY;
930 else if (sr & UARTSTAT_FE)
931 flg = TTY_FRAME;
932
933 if (sr & UARTSTAT_OR)
934 flg = TTY_OVERRUN;
935
936#ifdef SUPPORT_SYSRQ
937 sport->port.sysrq = 0;
938#endif
939 }
940
941 tty_insert_flip_char(port, rx, flg);
942 }
943
944out:
945 spin_unlock_irqrestore(&sport->port.lock, flags);
946
947 tty_flip_buffer_push(port);
Jingchang Lu380c9662014-07-14 17:41:11 +0800948}
949
Jingchang Luc9e2e942013-06-07 09:20:40 +0800950static irqreturn_t lpuart_int(int irq, void *dev_id)
951{
952 struct lpuart_port *sport = dev_id;
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530953 unsigned char sts;
Jingchang Luc9e2e942013-06-07 09:20:40 +0800954
955 sts = readb(sport->port.membase + UARTSR1);
956
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530957 if (sts & UARTSR1_RDRF)
Andrey Smirnov3993ddc2019-07-29 12:52:06 -0700958 lpuart_rxint(sport);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530959
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +0530960 if (sts & UARTSR1_TDRE)
Andrey Smirnov3993ddc2019-07-29 12:52:06 -0700961 lpuart_txint(sport);
Jingchang Luc9e2e942013-06-07 09:20:40 +0800962
963 return IRQ_HANDLED;
964}
965
Jingchang Lu380c9662014-07-14 17:41:11 +0800966static irqreturn_t lpuart32_int(int irq, void *dev_id)
967{
968 struct lpuart_port *sport = dev_id;
969 unsigned long sts, rxcount;
970
Dong Aishenga0204f22017-06-13 10:55:49 +0800971 sts = lpuart32_read(&sport->port, UARTSTAT);
972 rxcount = lpuart32_read(&sport->port, UARTWATER);
Jingchang Lu380c9662014-07-14 17:41:11 +0800973 rxcount = rxcount >> UARTWATER_RXCNT_OFF;
974
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900975 if ((sts & UARTSTAT_RDRF || rxcount > 0) && !sport->lpuart_dma_rx_use)
Andrey Smirnov3993ddc2019-07-29 12:52:06 -0700976 lpuart32_rxint(sport);
Jingchang Lu380c9662014-07-14 17:41:11 +0800977
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900978 if ((sts & UARTSTAT_TDRE) && !sport->lpuart_dma_tx_use)
Andrey Smirnov93b95232019-07-29 12:52:11 -0700979 lpuart32_txint(sport);
Jingchang Lu380c9662014-07-14 17:41:11 +0800980
Dong Aishenga0204f22017-06-13 10:55:49 +0800981 lpuart32_write(&sport->port, sts, UARTSTAT);
Jingchang Lu380c9662014-07-14 17:41:11 +0800982 return IRQ_HANDLED;
983}
984
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530985static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
986{
987 struct tty_port *port = &sport->port.state->port;
988 struct dma_tx_state state;
989 enum dma_status dmastat;
990 struct circ_buf *ring = &sport->rx_ring;
991 unsigned long flags;
992 int count = 0;
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530993
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900994 if (lpuart_is_32(sport)) {
995 unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +0530996
Atsushi Nemoto42b68762019-01-23 12:20:17 +0900997 if (sr & (UARTSTAT_PE | UARTSTAT_FE)) {
998 /* Read DR to clear the error flags */
999 lpuart32_read(&sport->port, UARTDATA);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301000
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001001 if (sr & UARTSTAT_PE)
1002 sport->port.icount.parity++;
1003 else if (sr & UARTSTAT_FE)
1004 sport->port.icount.frame++;
1005 }
1006 } else {
1007 unsigned char sr = readb(sport->port.membase + UARTSR1);
1008
1009 if (sr & (UARTSR1_PE | UARTSR1_FE)) {
Stefan Agner65632172019-07-29 12:52:03 -07001010 unsigned char cr2;
1011
1012 /* Disable receiver during this operation... */
1013 cr2 = readb(sport->port.membase + UARTCR2);
1014 cr2 &= ~UARTCR2_RE;
1015 writeb(cr2, sport->port.membase + UARTCR2);
1016
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001017 /* Read DR to clear the error flags */
1018 readb(sport->port.membase + UARTDR);
1019
1020 if (sr & UARTSR1_PE)
1021 sport->port.icount.parity++;
1022 else if (sr & UARTSR1_FE)
1023 sport->port.icount.frame++;
Stefan Agner65632172019-07-29 12:52:03 -07001024 /*
1025 * At this point parity/framing error is
1026 * cleared However, since the DMA already read
1027 * the data register and we had to read it
1028 * again after reading the status register to
1029 * properly clear the flags, the FIFO actually
1030 * underflowed... This requires a clearing of
1031 * the FIFO...
1032 */
1033 if (readb(sport->port.membase + UARTSFIFO) &
1034 UARTSFIFO_RXUF) {
1035 writeb(UARTSFIFO_RXUF,
1036 sport->port.membase + UARTSFIFO);
1037 writeb(UARTCFIFO_RXFLUSH,
1038 sport->port.membase + UARTCFIFO);
1039 }
1040
1041 cr2 |= UARTCR2_RE;
1042 writeb(cr2, sport->port.membase + UARTCR2);
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001043 }
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301044 }
1045
1046 async_tx_ack(sport->dma_rx_desc);
1047
1048 spin_lock_irqsave(&sport->port.lock, flags);
1049
1050 dmastat = dmaengine_tx_status(sport->dma_rx_chan,
1051 sport->dma_rx_cookie,
1052 &state);
1053
1054 if (dmastat == DMA_ERROR) {
1055 dev_err(sport->port.dev, "Rx DMA transfer failed!\n");
1056 spin_unlock_irqrestore(&sport->port.lock, flags);
1057 return;
1058 }
1059
1060 /* CPU claims ownership of RX DMA buffer */
1061 dma_sync_sg_for_cpu(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
1062
1063 /*
1064 * ring->head points to the end of data already written by the DMA.
1065 * ring->tail points to the beginning of data to be read by the
1066 * framework.
1067 * The current transfer size should not be larger than the dma buffer
1068 * length.
1069 */
1070 ring->head = sport->rx_sgl.length - state.residue;
1071 BUG_ON(ring->head > sport->rx_sgl.length);
1072 /*
1073 * At this point ring->head may point to the first byte right after the
1074 * last byte of the dma buffer:
1075 * 0 <= ring->head <= sport->rx_sgl.length
1076 *
1077 * However ring->tail must always points inside the dma buffer:
1078 * 0 <= ring->tail <= sport->rx_sgl.length - 1
1079 *
1080 * Since we use a ring buffer, we have to handle the case
1081 * where head is lower than tail. In such a case, we first read from
1082 * tail to the end of the buffer then reset tail.
1083 */
1084 if (ring->head < ring->tail) {
1085 count = sport->rx_sgl.length - ring->tail;
1086
1087 tty_insert_flip_string(port, ring->buf + ring->tail, count);
1088 ring->tail = 0;
1089 sport->port.icount.rx += count;
1090 }
1091
1092 /* Finally we read data from tail to head */
1093 if (ring->tail < ring->head) {
1094 count = ring->head - ring->tail;
1095 tty_insert_flip_string(port, ring->buf + ring->tail, count);
1096 /* Wrap ring->head if needed */
1097 if (ring->head >= sport->rx_sgl.length)
1098 ring->head = 0;
1099 ring->tail = ring->head;
1100 sport->port.icount.rx += count;
1101 }
1102
1103 dma_sync_sg_for_device(sport->port.dev, &sport->rx_sgl, 1,
1104 DMA_FROM_DEVICE);
1105
1106 spin_unlock_irqrestore(&sport->port.lock, flags);
1107
1108 tty_flip_buffer_push(port);
1109 mod_timer(&sport->lpuart_timer, jiffies + sport->dma_rx_timeout);
1110}
1111
1112static void lpuart_dma_rx_complete(void *arg)
1113{
1114 struct lpuart_port *sport = arg;
1115
1116 lpuart_copy_rx_to_tty(sport);
1117}
1118
Kees Cooke99e88a2017-10-16 14:43:17 -07001119static void lpuart_timer_func(struct timer_list *t)
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301120{
Kees Cooke99e88a2017-10-16 14:43:17 -07001121 struct lpuart_port *sport = from_timer(sport, t, lpuart_timer);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301122
1123 lpuart_copy_rx_to_tty(sport);
1124}
1125
1126static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
1127{
1128 struct dma_slave_config dma_rx_sconfig = {};
1129 struct circ_buf *ring = &sport->rx_ring;
1130 int ret, nent;
1131 int bits, baud;
Stefan Agner3216c622018-08-28 12:44:24 +02001132 struct tty_port *port = &sport->port.state->port;
1133 struct tty_struct *tty = port->tty;
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301134 struct ktermios *termios = &tty->termios;
1135
1136 baud = tty_get_baud_rate(tty);
1137
1138 bits = (termios->c_cflag & CSIZE) == CS7 ? 9 : 10;
1139 if (termios->c_cflag & PARENB)
1140 bits++;
1141
1142 /*
1143 * Calculate length of one DMA buffer size to keep latency below
1144 * 10ms at any baud rate.
1145 */
1146 sport->rx_dma_rng_buf_len = (DMA_RX_TIMEOUT * baud / bits / 1000) * 2;
1147 sport->rx_dma_rng_buf_len = (1 << (fls(sport->rx_dma_rng_buf_len) - 1));
1148 if (sport->rx_dma_rng_buf_len < 16)
1149 sport->rx_dma_rng_buf_len = 16;
1150
Fugang Duanca8d92f2019-07-17 13:19:28 +08001151 ring->buf = kzalloc(sport->rx_dma_rng_buf_len, GFP_ATOMIC);
Fabio Estevam099f79c2019-06-11 10:03:39 -03001152 if (!ring->buf)
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301153 return -ENOMEM;
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301154
1155 sg_init_one(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301156 nent = dma_map_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
1157
1158 if (!nent) {
1159 dev_err(sport->port.dev, "DMA Rx mapping error\n");
1160 return -EINVAL;
1161 }
1162
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001163 dma_rx_sconfig.src_addr = lpuart_dma_datareg_addr(sport);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301164 dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1165 dma_rx_sconfig.src_maxburst = 1;
1166 dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
1167 ret = dmaengine_slave_config(sport->dma_rx_chan, &dma_rx_sconfig);
1168
1169 if (ret < 0) {
1170 dev_err(sport->port.dev,
1171 "DMA Rx slave config failed, err = %d\n", ret);
1172 return ret;
1173 }
1174
1175 sport->dma_rx_desc = dmaengine_prep_dma_cyclic(sport->dma_rx_chan,
1176 sg_dma_address(&sport->rx_sgl),
1177 sport->rx_sgl.length,
1178 sport->rx_sgl.length / 2,
1179 DMA_DEV_TO_MEM,
1180 DMA_PREP_INTERRUPT);
1181 if (!sport->dma_rx_desc) {
1182 dev_err(sport->port.dev, "Cannot prepare cyclic DMA\n");
1183 return -EFAULT;
1184 }
1185
1186 sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
1187 sport->dma_rx_desc->callback_param = sport;
1188 sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
1189 dma_async_issue_pending(sport->dma_rx_chan);
1190
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001191 if (lpuart_is_32(sport)) {
1192 unsigned long temp = lpuart32_read(&sport->port, UARTBAUD);
1193
1194 lpuart32_write(&sport->port, temp | UARTBAUD_RDMAE, UARTBAUD);
1195 } else {
1196 writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_RDMAS,
1197 sport->port.membase + UARTCR5);
1198 }
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301199
1200 return 0;
1201}
1202
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301203static void lpuart_dma_rx_free(struct uart_port *port)
1204{
1205 struct lpuart_port *sport = container_of(port,
1206 struct lpuart_port, port);
1207
1208 if (sport->dma_rx_chan)
1209 dmaengine_terminate_all(sport->dma_rx_chan);
1210
1211 dma_unmap_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
1212 kfree(sport->rx_ring.buf);
1213 sport->rx_ring.tail = 0;
1214 sport->rx_ring.head = 0;
1215 sport->dma_rx_desc = NULL;
1216 sport->dma_rx_cookie = -EINVAL;
1217}
1218
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301219static int lpuart_config_rs485(struct uart_port *port,
1220 struct serial_rs485 *rs485)
1221{
1222 struct lpuart_port *sport = container_of(port,
1223 struct lpuart_port, port);
1224
1225 u8 modem = readb(sport->port.membase + UARTMODEM) &
1226 ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE);
1227 writeb(modem, sport->port.membase + UARTMODEM);
1228
Uwe Kleine-König68c338e2017-07-18 12:59:40 +02001229 /* clear unsupported configurations */
1230 rs485->delay_rts_before_send = 0;
1231 rs485->delay_rts_after_send = 0;
1232 rs485->flags &= ~SER_RS485_RX_DURING_TX;
1233
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301234 if (rs485->flags & SER_RS485_ENABLED) {
1235 /* Enable auto RS-485 RTS mode */
1236 modem |= UARTMODEM_TXRTSE;
1237
1238 /*
1239 * RTS needs to be logic HIGH either during transer _or_ after
1240 * transfer, other variants are not supported by the hardware.
1241 */
1242
1243 if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
1244 SER_RS485_RTS_AFTER_SEND)))
1245 rs485->flags |= SER_RS485_RTS_ON_SEND;
1246
1247 if (rs485->flags & SER_RS485_RTS_ON_SEND &&
1248 rs485->flags & SER_RS485_RTS_AFTER_SEND)
1249 rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
1250
1251 /*
1252 * The hardware defaults to RTS logic HIGH while transfer.
1253 * Switch polarity in case RTS shall be logic HIGH
1254 * after transfer.
1255 * Note: UART is assumed to be active high.
1256 */
1257 if (rs485->flags & SER_RS485_RTS_ON_SEND)
1258 modem &= ~UARTMODEM_TXRTSPOL;
1259 else if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
1260 modem |= UARTMODEM_TXRTSPOL;
1261 }
1262
1263 /* Store the new configuration */
1264 sport->port.rs485 = *rs485;
1265
1266 writeb(modem, sport->port.membase + UARTMODEM);
1267 return 0;
1268}
1269
Jingchang Luc9e2e942013-06-07 09:20:40 +08001270static unsigned int lpuart_get_mctrl(struct uart_port *port)
1271{
1272 unsigned int temp = 0;
1273 unsigned char reg;
1274
1275 reg = readb(port->membase + UARTMODEM);
1276 if (reg & UARTMODEM_TXCTSE)
1277 temp |= TIOCM_CTS;
1278
1279 if (reg & UARTMODEM_RXRTSE)
1280 temp |= TIOCM_RTS;
1281
1282 return temp;
1283}
1284
Jingchang Lu380c9662014-07-14 17:41:11 +08001285static unsigned int lpuart32_get_mctrl(struct uart_port *port)
1286{
1287 unsigned int temp = 0;
1288 unsigned long reg;
1289
Dong Aishenga0204f22017-06-13 10:55:49 +08001290 reg = lpuart32_read(port, UARTMODIR);
Jingchang Lu380c9662014-07-14 17:41:11 +08001291 if (reg & UARTMODIR_TXCTSE)
1292 temp |= TIOCM_CTS;
1293
1294 if (reg & UARTMODIR_RXRTSE)
1295 temp |= TIOCM_RTS;
1296
1297 return temp;
1298}
1299
Jingchang Luc9e2e942013-06-07 09:20:40 +08001300static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
1301{
1302 unsigned char temp;
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301303 struct lpuart_port *sport = container_of(port,
1304 struct lpuart_port, port);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001305
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301306 /* Make sure RXRTSE bit is not set when RS485 is enabled */
1307 if (!(sport->port.rs485.flags & SER_RS485_ENABLED)) {
1308 temp = readb(sport->port.membase + UARTMODEM) &
Jingchang Luc9e2e942013-06-07 09:20:40 +08001309 ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
1310
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301311 if (mctrl & TIOCM_RTS)
1312 temp |= UARTMODEM_RXRTSE;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001313
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301314 if (mctrl & TIOCM_CTS)
1315 temp |= UARTMODEM_TXCTSE;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001316
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301317 writeb(temp, port->membase + UARTMODEM);
1318 }
Jingchang Luc9e2e942013-06-07 09:20:40 +08001319}
1320
Jingchang Lu380c9662014-07-14 17:41:11 +08001321static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
1322{
1323 unsigned long temp;
1324
Dong Aishenga0204f22017-06-13 10:55:49 +08001325 temp = lpuart32_read(port, UARTMODIR) &
Jingchang Lu380c9662014-07-14 17:41:11 +08001326 ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
1327
1328 if (mctrl & TIOCM_RTS)
1329 temp |= UARTMODIR_RXRTSE;
1330
1331 if (mctrl & TIOCM_CTS)
1332 temp |= UARTMODIR_TXCTSE;
1333
Dong Aishenga0204f22017-06-13 10:55:49 +08001334 lpuart32_write(port, temp, UARTMODIR);
Jingchang Lu380c9662014-07-14 17:41:11 +08001335}
1336
Jingchang Luc9e2e942013-06-07 09:20:40 +08001337static void lpuart_break_ctl(struct uart_port *port, int break_state)
1338{
1339 unsigned char temp;
1340
1341 temp = readb(port->membase + UARTCR2) & ~UARTCR2_SBK;
1342
1343 if (break_state != 0)
1344 temp |= UARTCR2_SBK;
1345
1346 writeb(temp, port->membase + UARTCR2);
1347}
1348
Jingchang Lu380c9662014-07-14 17:41:11 +08001349static void lpuart32_break_ctl(struct uart_port *port, int break_state)
1350{
1351 unsigned long temp;
1352
Dong Aishenga0204f22017-06-13 10:55:49 +08001353 temp = lpuart32_read(port, UARTCTRL) & ~UARTCTRL_SBK;
Jingchang Lu380c9662014-07-14 17:41:11 +08001354
1355 if (break_state != 0)
1356 temp |= UARTCTRL_SBK;
1357
Dong Aishenga0204f22017-06-13 10:55:49 +08001358 lpuart32_write(port, temp, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001359}
1360
Jingchang Luc9e2e942013-06-07 09:20:40 +08001361static void lpuart_setup_watermark(struct lpuart_port *sport)
1362{
1363 unsigned char val, cr2;
Shawn Guobc764b82013-07-08 15:53:38 +08001364 unsigned char cr2_saved;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001365
1366 cr2 = readb(sport->port.membase + UARTCR2);
Shawn Guobc764b82013-07-08 15:53:38 +08001367 cr2_saved = cr2;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001368 cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_TE |
1369 UARTCR2_RIE | UARTCR2_RE);
1370 writeb(cr2, sport->port.membase + UARTCR2);
1371
Jingchang Luc9e2e942013-06-07 09:20:40 +08001372 val = readb(sport->port.membase + UARTPFIFO);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001373 writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
1374 sport->port.membase + UARTPFIFO);
1375
1376 /* flush Tx and Rx FIFO */
1377 writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
1378 sport->port.membase + UARTCFIFO);
1379
Stefan Agnerd68827c2016-07-19 13:13:05 +05301380 /* explicitly clear RDRF */
1381 if (readb(sport->port.membase + UARTSR1) & UARTSR1_RDRF) {
1382 readb(sport->port.membase + UARTDR);
1383 writeb(UARTSFIFO_RXUF, sport->port.membase + UARTSFIFO);
1384 }
1385
Yuan Yaof1cd8c82014-02-17 13:28:07 +08001386 writeb(0, sport->port.membase + UARTTWFIFO);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001387 writeb(1, sport->port.membase + UARTRWFIFO);
Shawn Guobc764b82013-07-08 15:53:38 +08001388
1389 /* Restore cr2 */
1390 writeb(cr2_saved, sport->port.membase + UARTCR2);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001391}
1392
Jingchang Lu380c9662014-07-14 17:41:11 +08001393static void lpuart32_setup_watermark(struct lpuart_port *sport)
1394{
1395 unsigned long val, ctrl;
1396 unsigned long ctrl_saved;
1397
Dong Aishenga0204f22017-06-13 10:55:49 +08001398 ctrl = lpuart32_read(&sport->port, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001399 ctrl_saved = ctrl;
1400 ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_TE |
1401 UARTCTRL_RIE | UARTCTRL_RE);
Dong Aishenga0204f22017-06-13 10:55:49 +08001402 lpuart32_write(&sport->port, ctrl, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001403
1404 /* enable FIFO mode */
Dong Aishenga0204f22017-06-13 10:55:49 +08001405 val = lpuart32_read(&sport->port, UARTFIFO);
Jingchang Lu380c9662014-07-14 17:41:11 +08001406 val |= UARTFIFO_TXFE | UARTFIFO_RXFE;
1407 val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
Dong Aishenga0204f22017-06-13 10:55:49 +08001408 lpuart32_write(&sport->port, val, UARTFIFO);
Jingchang Lu380c9662014-07-14 17:41:11 +08001409
1410 /* set the watermark */
1411 val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
Dong Aishenga0204f22017-06-13 10:55:49 +08001412 lpuart32_write(&sport->port, val, UARTWATER);
Jingchang Lu380c9662014-07-14 17:41:11 +08001413
1414 /* Restore cr2 */
Dong Aishenga0204f22017-06-13 10:55:49 +08001415 lpuart32_write(&sport->port, ctrl_saved, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001416}
1417
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301418static void rx_dma_timer_init(struct lpuart_port *sport)
Yuan Yaof1cd8c82014-02-17 13:28:07 +08001419{
Andrey Smirnov834a9742019-07-29 12:52:07 -07001420 timer_setup(&sport->lpuart_timer, lpuart_timer_func, 0);
1421 sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
1422 add_timer(&sport->lpuart_timer);
Yuan Yaof1cd8c82014-02-17 13:28:07 +08001423}
1424
Jingchang Luc9e2e942013-06-07 09:20:40 +08001425static int lpuart_startup(struct uart_port *port)
1426{
1427 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001428 unsigned long flags;
1429 unsigned char temp;
1430
Stefan Agnered9891b2014-07-02 18:02:57 +02001431 /* determine FIFO size and enable FIFO mode */
1432 temp = readb(sport->port.membase + UARTPFIFO);
1433
Fugang Duanf77ebb22019-07-17 13:19:30 +08001434 sport->txfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_TXSIZE_OFF) &
1435 UARTPFIFO_FIFOSIZE_MASK);
Stefan Agner4e8f2452015-03-13 14:51:50 +01001436 sport->port.fifosize = sport->txfifo_size;
1437
Fugang Duanf77ebb22019-07-17 13:19:30 +08001438 sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_RXSIZE_OFF) &
1439 UARTPFIFO_FIFOSIZE_MASK);
Stefan Agnered9891b2014-07-02 18:02:57 +02001440
Jingchang Luc9e2e942013-06-07 09:20:40 +08001441 spin_lock_irqsave(&sport->port.lock, flags);
1442
1443 lpuart_setup_watermark(sport);
1444
1445 temp = readb(sport->port.membase + UARTCR2);
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07001446 temp |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001447 writeb(temp, sport->port.membase + UARTCR2);
1448
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301449 if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
1450 /* set Rx DMA timeout */
1451 sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
1452 if (!sport->dma_rx_timeout)
1453 sport->dma_rx_timeout = 1;
1454
1455 sport->lpuart_dma_rx_use = true;
1456 rx_dma_timer_init(sport);
1457 } else {
1458 sport->lpuart_dma_rx_use = false;
1459 }
1460
1461 if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +05301462 init_waitqueue_head(&sport->dma_wait);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301463 sport->lpuart_dma_tx_use = true;
1464 temp = readb(port->membase + UARTCR5);
1465 writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
1466 } else {
1467 sport->lpuart_dma_tx_use = false;
1468 }
1469
Jingchang Luc9e2e942013-06-07 09:20:40 +08001470 spin_unlock_irqrestore(&sport->port.lock, flags);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301471
Jingchang Luc9e2e942013-06-07 09:20:40 +08001472 return 0;
1473}
1474
Jingchang Lu380c9662014-07-14 17:41:11 +08001475static int lpuart32_startup(struct uart_port *port)
1476{
1477 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
Jingchang Lu380c9662014-07-14 17:41:11 +08001478 unsigned long flags;
1479 unsigned long temp;
1480
1481 /* determine FIFO size */
Dong Aishenga0204f22017-06-13 10:55:49 +08001482 temp = lpuart32_read(&sport->port, UARTFIFO);
Jingchang Lu380c9662014-07-14 17:41:11 +08001483
Fugang Duanf77ebb22019-07-17 13:19:30 +08001484 sport->txfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_TXSIZE_OFF) &
1485 UARTFIFO_FIFOSIZE_MASK);
Atsushi Nemotob0b2735a2019-01-21 17:36:21 +09001486 sport->port.fifosize = sport->txfifo_size;
1487
Fugang Duanf77ebb22019-07-17 13:19:30 +08001488 sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_RXSIZE_OFF) &
1489 UARTFIFO_FIFOSIZE_MASK);
Jingchang Lu380c9662014-07-14 17:41:11 +08001490
Jingchang Lu380c9662014-07-14 17:41:11 +08001491 spin_lock_irqsave(&sport->port.lock, flags);
1492
1493 lpuart32_setup_watermark(sport);
1494
Dong Aishenga0204f22017-06-13 10:55:49 +08001495 temp = lpuart32_read(&sport->port, UARTCTRL);
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001496 temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
1497 lpuart32_write(&sport->port, temp, UARTCTRL);
1498
1499 if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
1500 /* set Rx DMA timeout */
1501 sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
1502 if (!sport->dma_rx_timeout)
1503 sport->dma_rx_timeout = 1;
1504
1505 sport->lpuart_dma_rx_use = true;
1506 rx_dma_timer_init(sport);
1507 } else {
1508 sport->lpuart_dma_rx_use = false;
1509 }
1510
1511 if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
1512 init_waitqueue_head(&sport->dma_wait);
1513 sport->lpuart_dma_tx_use = true;
1514 temp = lpuart32_read(&sport->port, UARTBAUD);
1515 lpuart32_write(&sport->port, temp | UARTBAUD_TDMAE, UARTBAUD);
1516 } else {
1517 sport->lpuart_dma_tx_use = false;
1518 }
1519
1520 if (sport->lpuart_dma_rx_use) {
1521 /* RXWATER must be 0 */
1522 temp = lpuart32_read(&sport->port, UARTWATER);
1523 temp &= ~(UARTWATER_WATER_MASK << UARTWATER_RXWATER_OFF);
1524 lpuart32_write(&sport->port, temp, UARTWATER);
1525 }
1526 temp = lpuart32_read(&sport->port, UARTCTRL);
1527 if (!sport->lpuart_dma_rx_use)
1528 temp |= UARTCTRL_RIE;
1529 if (!sport->lpuart_dma_tx_use)
1530 temp |= UARTCTRL_TIE;
Dong Aishenga0204f22017-06-13 10:55:49 +08001531 lpuart32_write(&sport->port, temp, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001532
1533 spin_unlock_irqrestore(&sport->port.lock, flags);
1534 return 0;
1535}
1536
Jingchang Luc9e2e942013-06-07 09:20:40 +08001537static void lpuart_shutdown(struct uart_port *port)
1538{
1539 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
1540 unsigned char temp;
1541 unsigned long flags;
1542
1543 spin_lock_irqsave(&port->lock, flags);
1544
1545 /* disable Rx/Tx and interrupts */
1546 temp = readb(port->membase + UARTCR2);
1547 temp &= ~(UARTCR2_TE | UARTCR2_RE |
1548 UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE);
1549 writeb(temp, port->membase + UARTCR2);
1550
1551 spin_unlock_irqrestore(&port->lock, flags);
1552
Stefan Agner4a818c42015-01-10 09:33:45 +01001553 if (sport->lpuart_dma_rx_use) {
Stefan Agner4a8588a2015-01-10 01:08:58 +01001554 del_timer_sync(&sport->lpuart_timer);
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301555 lpuart_dma_rx_free(&sport->port);
Yuan Yaof1cd8c82014-02-17 13:28:07 +08001556 }
Stefan Agner4a818c42015-01-10 09:33:45 +01001557
Bhuvanchandra DV6250cc32016-07-19 13:13:08 +05301558 if (sport->lpuart_dma_tx_use) {
1559 if (wait_event_interruptible(sport->dma_wait,
1560 !sport->dma_tx_in_progress) != false) {
1561 sport->dma_tx_in_progress = false;
1562 dmaengine_terminate_all(sport->dma_tx_chan);
1563 }
1564
1565 lpuart_stop_tx(port);
1566 }
Jingchang Luc9e2e942013-06-07 09:20:40 +08001567}
1568
Jingchang Lu380c9662014-07-14 17:41:11 +08001569static void lpuart32_shutdown(struct uart_port *port)
1570{
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001571 struct lpuart_port *sport =
1572 container_of(port, struct lpuart_port, port);
Jingchang Lu380c9662014-07-14 17:41:11 +08001573 unsigned long temp;
1574 unsigned long flags;
1575
1576 spin_lock_irqsave(&port->lock, flags);
1577
1578 /* disable Rx/Tx and interrupts */
Dong Aishenga0204f22017-06-13 10:55:49 +08001579 temp = lpuart32_read(port, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001580 temp &= ~(UARTCTRL_TE | UARTCTRL_RE |
1581 UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
Dong Aishenga0204f22017-06-13 10:55:49 +08001582 lpuart32_write(port, temp, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001583
1584 spin_unlock_irqrestore(&port->lock, flags);
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001585
1586 if (sport->lpuart_dma_rx_use) {
1587 del_timer_sync(&sport->lpuart_timer);
1588 lpuart_dma_rx_free(&sport->port);
1589 }
1590
1591 if (sport->lpuart_dma_tx_use) {
1592 if (wait_event_interruptible(sport->dma_wait,
1593 !sport->dma_tx_in_progress)) {
1594 sport->dma_tx_in_progress = false;
1595 dmaengine_terminate_all(sport->dma_tx_chan);
1596 }
1597
1598 lpuart32_stop_tx(port);
1599 }
Jingchang Lu380c9662014-07-14 17:41:11 +08001600}
1601
Jingchang Luc9e2e942013-06-07 09:20:40 +08001602static void
1603lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
1604 struct ktermios *old)
1605{
1606 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
1607 unsigned long flags;
Bhuvanchandra DVaa9e7d72016-07-19 13:13:06 +05301608 unsigned char cr1, old_cr1, old_cr2, cr3, cr4, bdh, modem;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001609 unsigned int baud;
1610 unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
1611 unsigned int sbr, brfa;
1612
1613 cr1 = old_cr1 = readb(sport->port.membase + UARTCR1);
1614 old_cr2 = readb(sport->port.membase + UARTCR2);
Bhuvanchandra DVaa9e7d72016-07-19 13:13:06 +05301615 cr3 = readb(sport->port.membase + UARTCR3);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001616 cr4 = readb(sport->port.membase + UARTCR4);
1617 bdh = readb(sport->port.membase + UARTBDH);
1618 modem = readb(sport->port.membase + UARTMODEM);
1619 /*
1620 * only support CS8 and CS7, and for CS7 must enable PE.
1621 * supported mode:
1622 * - (7,e/o,1)
1623 * - (8,n,1)
1624 * - (8,m/s,1)
1625 * - (8,e/o,1)
1626 */
1627 while ((termios->c_cflag & CSIZE) != CS8 &&
1628 (termios->c_cflag & CSIZE) != CS7) {
1629 termios->c_cflag &= ~CSIZE;
1630 termios->c_cflag |= old_csize;
1631 old_csize = CS8;
1632 }
1633
1634 if ((termios->c_cflag & CSIZE) == CS8 ||
1635 (termios->c_cflag & CSIZE) == CS7)
1636 cr1 = old_cr1 & ~UARTCR1_M;
1637
1638 if (termios->c_cflag & CMSPAR) {
1639 if ((termios->c_cflag & CSIZE) != CS8) {
1640 termios->c_cflag &= ~CSIZE;
1641 termios->c_cflag |= CS8;
1642 }
1643 cr1 |= UARTCR1_M;
1644 }
1645
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05301646 /*
1647 * When auto RS-485 RTS mode is enabled,
1648 * hardware flow control need to be disabled.
1649 */
1650 if (sport->port.rs485.flags & SER_RS485_ENABLED)
1651 termios->c_cflag &= ~CRTSCTS;
1652
Andrey Smirnovd26454e2019-07-29 12:52:12 -07001653 if (termios->c_cflag & CRTSCTS)
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07001654 modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE;
Andrey Smirnovd26454e2019-07-29 12:52:12 -07001655 else
Jingchang Luc9e2e942013-06-07 09:20:40 +08001656 modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001657
Andrey Smirnov76e3f2a2019-07-29 12:52:14 -07001658 termios->c_cflag &= ~CSTOPB;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001659
1660 /* parity must be enabled when CS7 to match 8-bits format */
1661 if ((termios->c_cflag & CSIZE) == CS7)
1662 termios->c_cflag |= PARENB;
1663
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07001664 if (termios->c_cflag & PARENB) {
Jingchang Luc9e2e942013-06-07 09:20:40 +08001665 if (termios->c_cflag & CMSPAR) {
1666 cr1 &= ~UARTCR1_PE;
Bhuvanchandra DVaa9e7d72016-07-19 13:13:06 +05301667 if (termios->c_cflag & PARODD)
1668 cr3 |= UARTCR3_T8;
1669 else
1670 cr3 &= ~UARTCR3_T8;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001671 } else {
1672 cr1 |= UARTCR1_PE;
1673 if ((termios->c_cflag & CSIZE) == CS8)
1674 cr1 |= UARTCR1_M;
1675 if (termios->c_cflag & PARODD)
1676 cr1 |= UARTCR1_PT;
1677 else
1678 cr1 &= ~UARTCR1_PT;
1679 }
Andy Duan397bd922018-10-16 07:32:22 +00001680 } else {
1681 cr1 &= ~UARTCR1_PE;
Jingchang Luc9e2e942013-06-07 09:20:40 +08001682 }
1683
1684 /* ask the core to calculate the divisor */
1685 baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
1686
Nikita Yushchenko54a44d52016-12-04 18:49:28 +03001687 /*
1688 * Need to update the Ring buffer length according to the selected
1689 * baud rate and restart Rx DMA path.
1690 *
1691 * Since timer function acqures sport->port.lock, need to stop before
1692 * acquring same lock because otherwise del_timer_sync() can deadlock.
1693 */
1694 if (old && sport->lpuart_dma_rx_use) {
1695 del_timer_sync(&sport->lpuart_timer);
1696 lpuart_dma_rx_free(&sport->port);
1697 }
1698
Jingchang Luc9e2e942013-06-07 09:20:40 +08001699 spin_lock_irqsave(&sport->port.lock, flags);
1700
1701 sport->port.read_status_mask = 0;
1702 if (termios->c_iflag & INPCK)
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07001703 sport->port.read_status_mask |= UARTSR1_FE | UARTSR1_PE;
Peter Hurleyef8b9dd2014-06-16 08:10:41 -04001704 if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
Jingchang Luc9e2e942013-06-07 09:20:40 +08001705 sport->port.read_status_mask |= UARTSR1_FE;
1706
1707 /* characters to ignore */
1708 sport->port.ignore_status_mask = 0;
1709 if (termios->c_iflag & IGNPAR)
1710 sport->port.ignore_status_mask |= UARTSR1_PE;
1711 if (termios->c_iflag & IGNBRK) {
1712 sport->port.ignore_status_mask |= UARTSR1_FE;
1713 /*
1714 * if we're ignoring parity and break indicators,
1715 * ignore overruns too (for real raw support).
1716 */
1717 if (termios->c_iflag & IGNPAR)
1718 sport->port.ignore_status_mask |= UARTSR1_OR;
1719 }
1720
1721 /* update the per-port timeout */
1722 uart_update_timeout(port, termios->c_cflag, baud);
1723
1724 /* wait transmit engin complete */
1725 while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
1726 barrier();
1727
1728 /* disable transmit and receive */
1729 writeb(old_cr2 & ~(UARTCR2_TE | UARTCR2_RE),
1730 sport->port.membase + UARTCR2);
1731
1732 sbr = sport->port.uartclk / (16 * baud);
1733 brfa = ((sport->port.uartclk - (16 * sbr * baud)) * 2) / baud;
1734 bdh &= ~UARTBDH_SBR_MASK;
1735 bdh |= (sbr >> 8) & 0x1F;
1736 cr4 &= ~UARTCR4_BRFA_MASK;
1737 brfa &= UARTCR4_BRFA_MASK;
1738 writeb(cr4 | brfa, sport->port.membase + UARTCR4);
1739 writeb(bdh, sport->port.membase + UARTBDH);
1740 writeb(sbr & 0xFF, sport->port.membase + UARTBDL);
Bhuvanchandra DVaa9e7d72016-07-19 13:13:06 +05301741 writeb(cr3, sport->port.membase + UARTCR3);
Jingchang Luc9e2e942013-06-07 09:20:40 +08001742 writeb(cr1, sport->port.membase + UARTCR1);
1743 writeb(modem, sport->port.membase + UARTMODEM);
1744
1745 /* restore control register */
1746 writeb(old_cr2, sport->port.membase + UARTCR2);
1747
Nikita Yushchenko54a44d52016-12-04 18:49:28 +03001748 if (old && sport->lpuart_dma_rx_use) {
1749 if (!lpuart_start_rx_dma(sport))
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301750 rx_dma_timer_init(sport);
Nikita Yushchenko54a44d52016-12-04 18:49:28 +03001751 else
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301752 sport->lpuart_dma_rx_use = false;
Bhuvanchandra DV5887ad42016-07-19 13:13:07 +05301753 }
1754
Jingchang Luc9e2e942013-06-07 09:20:40 +08001755 spin_unlock_irqrestore(&sport->port.lock, flags);
1756}
1757
Jingchang Lu380c9662014-07-14 17:41:11 +08001758static void
Dong Aishenga6d75142017-06-13 10:55:54 +08001759lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
1760{
1761 u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
1762 u32 clk = sport->port.uartclk;
1763
1764 /*
1765 * The idea is to use the best OSR (over-sampling rate) possible.
1766 * Note, OSR is typically hard-set to 16 in other LPUART instantiations.
1767 * Loop to find the best OSR value possible, one that generates minimum
1768 * baud_diff iterate through the rest of the supported values of OSR.
1769 *
1770 * Calculation Formula:
1771 * Baud Rate = baud clock / ((OSR+1) × SBR)
1772 */
1773 baud_diff = baudrate;
1774 osr = 0;
1775 sbr = 0;
1776
1777 for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
1778 /* calculate the temporary sbr value */
1779 tmp_sbr = (clk / (baudrate * tmp_osr));
1780 if (tmp_sbr == 0)
1781 tmp_sbr = 1;
1782
1783 /*
1784 * calculate the baud rate difference based on the temporary
1785 * osr and sbr values
1786 */
1787 tmp_diff = clk / (tmp_osr * tmp_sbr) - baudrate;
1788
1789 /* select best values between sbr and sbr+1 */
1790 tmp = clk / (tmp_osr * (tmp_sbr + 1));
1791 if (tmp_diff > (baudrate - tmp)) {
1792 tmp_diff = baudrate - tmp;
1793 tmp_sbr++;
1794 }
1795
1796 if (tmp_diff <= baud_diff) {
1797 baud_diff = tmp_diff;
1798 osr = tmp_osr;
1799 sbr = tmp_sbr;
1800
1801 if (!baud_diff)
1802 break;
1803 }
1804 }
1805
1806 /* handle buadrate outside acceptable rate */
1807 if (baud_diff > ((baudrate / 100) * 3))
1808 dev_warn(sport->port.dev,
1809 "unacceptable baud rate difference of more than 3%%\n");
1810
1811 tmp = lpuart32_read(&sport->port, UARTBAUD);
1812
1813 if ((osr > 3) && (osr < 8))
1814 tmp |= UARTBAUD_BOTHEDGE;
1815
1816 tmp &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT);
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07001817 tmp |= ((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT;
Dong Aishenga6d75142017-06-13 10:55:54 +08001818
1819 tmp &= ~UARTBAUD_SBR_MASK;
1820 tmp |= sbr & UARTBAUD_SBR_MASK;
1821
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001822 if (!sport->lpuart_dma_rx_use)
1823 tmp &= ~UARTBAUD_RDMAE;
1824 if (!sport->lpuart_dma_tx_use)
1825 tmp &= ~UARTBAUD_TDMAE;
Dong Aishenga6d75142017-06-13 10:55:54 +08001826
1827 lpuart32_write(&sport->port, tmp, UARTBAUD);
1828}
1829
1830static void
Jingchang Lu380c9662014-07-14 17:41:11 +08001831lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
1832 struct ktermios *old)
1833{
1834 struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
1835 unsigned long flags;
Fabio Estevamc45e2d22017-09-18 08:33:28 -03001836 unsigned long ctrl, old_ctrl, modem;
Jingchang Lu380c9662014-07-14 17:41:11 +08001837 unsigned int baud;
1838 unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
Jingchang Lu380c9662014-07-14 17:41:11 +08001839
Dong Aishenga0204f22017-06-13 10:55:49 +08001840 ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL);
Dong Aishenga0204f22017-06-13 10:55:49 +08001841 modem = lpuart32_read(&sport->port, UARTMODIR);
Jingchang Lu380c9662014-07-14 17:41:11 +08001842 /*
1843 * only support CS8 and CS7, and for CS7 must enable PE.
1844 * supported mode:
1845 * - (7,e/o,1)
1846 * - (8,n,1)
1847 * - (8,m/s,1)
1848 * - (8,e/o,1)
1849 */
1850 while ((termios->c_cflag & CSIZE) != CS8 &&
1851 (termios->c_cflag & CSIZE) != CS7) {
1852 termios->c_cflag &= ~CSIZE;
1853 termios->c_cflag |= old_csize;
1854 old_csize = CS8;
1855 }
1856
1857 if ((termios->c_cflag & CSIZE) == CS8 ||
1858 (termios->c_cflag & CSIZE) == CS7)
1859 ctrl = old_ctrl & ~UARTCTRL_M;
1860
1861 if (termios->c_cflag & CMSPAR) {
1862 if ((termios->c_cflag & CSIZE) != CS8) {
1863 termios->c_cflag &= ~CSIZE;
1864 termios->c_cflag |= CS8;
1865 }
1866 ctrl |= UARTCTRL_M;
1867 }
1868
1869 if (termios->c_cflag & CRTSCTS) {
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07001870 modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE;
Jingchang Lu380c9662014-07-14 17:41:11 +08001871 } else {
1872 termios->c_cflag &= ~CRTSCTS;
1873 modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
1874 }
1875
1876 if (termios->c_cflag & CSTOPB)
1877 termios->c_cflag &= ~CSTOPB;
1878
1879 /* parity must be enabled when CS7 to match 8-bits format */
1880 if ((termios->c_cflag & CSIZE) == CS7)
1881 termios->c_cflag |= PARENB;
1882
1883 if ((termios->c_cflag & PARENB)) {
1884 if (termios->c_cflag & CMSPAR) {
1885 ctrl &= ~UARTCTRL_PE;
1886 ctrl |= UARTCTRL_M;
1887 } else {
Andy Duan61e169e2018-10-16 07:32:19 +00001888 ctrl |= UARTCTRL_PE;
Jingchang Lu380c9662014-07-14 17:41:11 +08001889 if ((termios->c_cflag & CSIZE) == CS8)
1890 ctrl |= UARTCTRL_M;
1891 if (termios->c_cflag & PARODD)
1892 ctrl |= UARTCTRL_PT;
1893 else
1894 ctrl &= ~UARTCTRL_PT;
1895 }
Andy Duan397bd922018-10-16 07:32:22 +00001896 } else {
1897 ctrl &= ~UARTCTRL_PE;
Jingchang Lu380c9662014-07-14 17:41:11 +08001898 }
1899
1900 /* ask the core to calculate the divisor */
Tomonori Sakita815d8352019-01-21 17:34:16 +09001901 baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
Jingchang Lu380c9662014-07-14 17:41:11 +08001902
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001903 /*
1904 * Need to update the Ring buffer length according to the selected
1905 * baud rate and restart Rx DMA path.
1906 *
1907 * Since timer function acqures sport->port.lock, need to stop before
1908 * acquring same lock because otherwise del_timer_sync() can deadlock.
1909 */
1910 if (old && sport->lpuart_dma_rx_use) {
1911 del_timer_sync(&sport->lpuart_timer);
1912 lpuart_dma_rx_free(&sport->port);
1913 }
1914
Jingchang Lu380c9662014-07-14 17:41:11 +08001915 spin_lock_irqsave(&sport->port.lock, flags);
1916
1917 sport->port.read_status_mask = 0;
1918 if (termios->c_iflag & INPCK)
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07001919 sport->port.read_status_mask |= UARTSTAT_FE | UARTSTAT_PE;
Jingchang Lu380c9662014-07-14 17:41:11 +08001920 if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
1921 sport->port.read_status_mask |= UARTSTAT_FE;
1922
1923 /* characters to ignore */
1924 sport->port.ignore_status_mask = 0;
1925 if (termios->c_iflag & IGNPAR)
1926 sport->port.ignore_status_mask |= UARTSTAT_PE;
1927 if (termios->c_iflag & IGNBRK) {
1928 sport->port.ignore_status_mask |= UARTSTAT_FE;
1929 /*
1930 * if we're ignoring parity and break indicators,
1931 * ignore overruns too (for real raw support).
1932 */
1933 if (termios->c_iflag & IGNPAR)
1934 sport->port.ignore_status_mask |= UARTSTAT_OR;
1935 }
1936
1937 /* update the per-port timeout */
1938 uart_update_timeout(port, termios->c_cflag, baud);
1939
1940 /* wait transmit engin complete */
Dong Aishenga0204f22017-06-13 10:55:49 +08001941 while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC))
Jingchang Lu380c9662014-07-14 17:41:11 +08001942 barrier();
1943
1944 /* disable transmit and receive */
Dong Aishenga0204f22017-06-13 10:55:49 +08001945 lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
1946 UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001947
Dong Aishenga6d75142017-06-13 10:55:54 +08001948 lpuart32_serial_setbrg(sport, baud);
Dong Aishenga0204f22017-06-13 10:55:49 +08001949 lpuart32_write(&sport->port, modem, UARTMODIR);
1950 lpuart32_write(&sport->port, ctrl, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08001951 /* restore control register */
1952
Atsushi Nemoto42b68762019-01-23 12:20:17 +09001953 if (old && sport->lpuart_dma_rx_use) {
1954 if (!lpuart_start_rx_dma(sport))
1955 rx_dma_timer_init(sport);
1956 else
1957 sport->lpuart_dma_rx_use = false;
1958 }
1959
Jingchang Lu380c9662014-07-14 17:41:11 +08001960 spin_unlock_irqrestore(&sport->port.lock, flags);
1961}
1962
Jingchang Luc9e2e942013-06-07 09:20:40 +08001963static const char *lpuart_type(struct uart_port *port)
1964{
1965 return "FSL_LPUART";
1966}
1967
1968static void lpuart_release_port(struct uart_port *port)
1969{
1970 /* nothing to do */
1971}
1972
1973static int lpuart_request_port(struct uart_port *port)
1974{
1975 return 0;
1976}
1977
1978/* configure/autoconfigure the port */
1979static void lpuart_config_port(struct uart_port *port, int flags)
1980{
1981 if (flags & UART_CONFIG_TYPE)
1982 port->type = PORT_LPUART;
1983}
1984
1985static int lpuart_verify_port(struct uart_port *port, struct serial_struct *ser)
1986{
1987 int ret = 0;
1988
1989 if (ser->type != PORT_UNKNOWN && ser->type != PORT_LPUART)
1990 ret = -EINVAL;
1991 if (port->irq != ser->irq)
1992 ret = -EINVAL;
1993 if (ser->io_type != UPIO_MEM)
1994 ret = -EINVAL;
1995 if (port->uartclk / 16 != ser->baud_base)
1996 ret = -EINVAL;
1997 if (port->iobase != ser->port)
1998 ret = -EINVAL;
1999 if (ser->hub6 != 0)
2000 ret = -EINVAL;
2001 return ret;
2002}
2003
Julia Lawall069a47e2016-09-01 19:51:35 +02002004static const struct uart_ops lpuart_pops = {
Jingchang Luc9e2e942013-06-07 09:20:40 +08002005 .tx_empty = lpuart_tx_empty,
2006 .set_mctrl = lpuart_set_mctrl,
2007 .get_mctrl = lpuart_get_mctrl,
2008 .stop_tx = lpuart_stop_tx,
2009 .start_tx = lpuart_start_tx,
2010 .stop_rx = lpuart_stop_rx,
Jingchang Luc9e2e942013-06-07 09:20:40 +08002011 .break_ctl = lpuart_break_ctl,
2012 .startup = lpuart_startup,
2013 .shutdown = lpuart_shutdown,
2014 .set_termios = lpuart_set_termios,
2015 .type = lpuart_type,
2016 .request_port = lpuart_request_port,
2017 .release_port = lpuart_release_port,
2018 .config_port = lpuart_config_port,
2019 .verify_port = lpuart_verify_port,
Stefan Agnerbfc2e072015-01-26 01:10:16 +01002020 .flush_buffer = lpuart_flush_buffer,
Nicolae Rosia2a41bc22016-10-04 15:46:16 +03002021#if defined(CONFIG_CONSOLE_POLL)
2022 .poll_init = lpuart_poll_init,
2023 .poll_get_char = lpuart_poll_get_char,
2024 .poll_put_char = lpuart_poll_put_char,
2025#endif
Jingchang Luc9e2e942013-06-07 09:20:40 +08002026};
2027
Julia Lawall069a47e2016-09-01 19:51:35 +02002028static const struct uart_ops lpuart32_pops = {
Jingchang Lu380c9662014-07-14 17:41:11 +08002029 .tx_empty = lpuart32_tx_empty,
2030 .set_mctrl = lpuart32_set_mctrl,
2031 .get_mctrl = lpuart32_get_mctrl,
2032 .stop_tx = lpuart32_stop_tx,
2033 .start_tx = lpuart32_start_tx,
2034 .stop_rx = lpuart32_stop_rx,
2035 .break_ctl = lpuart32_break_ctl,
2036 .startup = lpuart32_startup,
2037 .shutdown = lpuart32_shutdown,
2038 .set_termios = lpuart32_set_termios,
2039 .type = lpuart_type,
2040 .request_port = lpuart_request_port,
2041 .release_port = lpuart_release_port,
2042 .config_port = lpuart_config_port,
2043 .verify_port = lpuart_verify_port,
Stefan Agnerbfc2e072015-01-26 01:10:16 +01002044 .flush_buffer = lpuart_flush_buffer,
Marius Vlada5fa2662017-07-16 01:00:58 +03002045#if defined(CONFIG_CONSOLE_POLL)
2046 .poll_init = lpuart32_poll_init,
2047 .poll_get_char = lpuart32_poll_get_char,
2048 .poll_put_char = lpuart32_poll_put_char,
2049#endif
Jingchang Lu380c9662014-07-14 17:41:11 +08002050};
2051
Jingchang Luc9e2e942013-06-07 09:20:40 +08002052static struct lpuart_port *lpuart_ports[UART_NR];
2053
2054#ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
2055static void lpuart_console_putchar(struct uart_port *port, int ch)
2056{
2057 while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE))
2058 barrier();
2059
2060 writeb(ch, port->membase + UARTDR);
2061}
2062
Jingchang Lu380c9662014-07-14 17:41:11 +08002063static void lpuart32_console_putchar(struct uart_port *port, int ch)
2064{
Dong Aishenga0204f22017-06-13 10:55:49 +08002065 while (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE))
Jingchang Lu380c9662014-07-14 17:41:11 +08002066 barrier();
2067
Dong Aishenga0204f22017-06-13 10:55:49 +08002068 lpuart32_write(port, ch, UARTDATA);
Jingchang Lu380c9662014-07-14 17:41:11 +08002069}
2070
Jingchang Luc9e2e942013-06-07 09:20:40 +08002071static void
2072lpuart_console_write(struct console *co, const char *s, unsigned int count)
2073{
2074 struct lpuart_port *sport = lpuart_ports[co->index];
2075 unsigned char old_cr2, cr2;
Stefan Agnerabf1e0a2017-03-24 11:33:46 -07002076 unsigned long flags;
2077 int locked = 1;
2078
2079 if (sport->port.sysrq || oops_in_progress)
2080 locked = spin_trylock_irqsave(&sport->port.lock, flags);
2081 else
2082 spin_lock_irqsave(&sport->port.lock, flags);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002083
2084 /* first save CR2 and then disable interrupts */
2085 cr2 = old_cr2 = readb(sport->port.membase + UARTCR2);
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07002086 cr2 |= UARTCR2_TE | UARTCR2_RE;
Jingchang Luc9e2e942013-06-07 09:20:40 +08002087 cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE);
2088 writeb(cr2, sport->port.membase + UARTCR2);
2089
2090 uart_console_write(&sport->port, s, count, lpuart_console_putchar);
2091
2092 /* wait for transmitter finish complete and restore CR2 */
2093 while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
2094 barrier();
2095
2096 writeb(old_cr2, sport->port.membase + UARTCR2);
Stefan Agnerabf1e0a2017-03-24 11:33:46 -07002097
2098 if (locked)
2099 spin_unlock_irqrestore(&sport->port.lock, flags);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002100}
2101
Jingchang Lu380c9662014-07-14 17:41:11 +08002102static void
2103lpuart32_console_write(struct console *co, const char *s, unsigned int count)
2104{
2105 struct lpuart_port *sport = lpuart_ports[co->index];
2106 unsigned long old_cr, cr;
Stefan Agnerabf1e0a2017-03-24 11:33:46 -07002107 unsigned long flags;
2108 int locked = 1;
2109
2110 if (sport->port.sysrq || oops_in_progress)
2111 locked = spin_trylock_irqsave(&sport->port.lock, flags);
2112 else
2113 spin_lock_irqsave(&sport->port.lock, flags);
Jingchang Lu380c9662014-07-14 17:41:11 +08002114
2115 /* first save CR2 and then disable interrupts */
Dong Aishenga0204f22017-06-13 10:55:49 +08002116 cr = old_cr = lpuart32_read(&sport->port, UARTCTRL);
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07002117 cr |= UARTCTRL_TE | UARTCTRL_RE;
Jingchang Lu380c9662014-07-14 17:41:11 +08002118 cr &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
Dong Aishenga0204f22017-06-13 10:55:49 +08002119 lpuart32_write(&sport->port, cr, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08002120
2121 uart_console_write(&sport->port, s, count, lpuart32_console_putchar);
2122
2123 /* wait for transmitter finish complete and restore CR2 */
Dong Aishenga0204f22017-06-13 10:55:49 +08002124 while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC))
Jingchang Lu380c9662014-07-14 17:41:11 +08002125 barrier();
2126
Dong Aishenga0204f22017-06-13 10:55:49 +08002127 lpuart32_write(&sport->port, old_cr, UARTCTRL);
Stefan Agnerabf1e0a2017-03-24 11:33:46 -07002128
2129 if (locked)
2130 spin_unlock_irqrestore(&sport->port.lock, flags);
Jingchang Lu380c9662014-07-14 17:41:11 +08002131}
2132
Jingchang Luc9e2e942013-06-07 09:20:40 +08002133/*
2134 * if the port was already initialised (eg, by a boot loader),
2135 * try to determine the current setup.
2136 */
2137static void __init
2138lpuart_console_get_options(struct lpuart_port *sport, int *baud,
2139 int *parity, int *bits)
2140{
2141 unsigned char cr, bdh, bdl, brfa;
2142 unsigned int sbr, uartclk, baud_raw;
2143
2144 cr = readb(sport->port.membase + UARTCR2);
2145 cr &= UARTCR2_TE | UARTCR2_RE;
2146 if (!cr)
2147 return;
2148
2149 /* ok, the port was enabled */
2150
2151 cr = readb(sport->port.membase + UARTCR1);
2152
2153 *parity = 'n';
2154 if (cr & UARTCR1_PE) {
2155 if (cr & UARTCR1_PT)
2156 *parity = 'o';
2157 else
2158 *parity = 'e';
2159 }
2160
2161 if (cr & UARTCR1_M)
2162 *bits = 9;
2163 else
2164 *bits = 8;
2165
2166 bdh = readb(sport->port.membase + UARTBDH);
2167 bdh &= UARTBDH_SBR_MASK;
2168 bdl = readb(sport->port.membase + UARTBDL);
2169 sbr = bdh;
2170 sbr <<= 8;
2171 sbr |= bdl;
2172 brfa = readb(sport->port.membase + UARTCR4);
2173 brfa &= UARTCR4_BRFA_MASK;
2174
Fugang Duan35a4ed02019-07-04 21:40:07 +08002175 uartclk = lpuart_get_baud_clk_rate(sport);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002176 /*
2177 * baud = mod_clk/(16*(sbr[13]+(brfa)/32)
2178 */
2179 baud_raw = uartclk / (16 * (sbr + brfa / 32));
2180
2181 if (*baud != baud_raw)
Fabio Estevam9edaf502019-06-04 00:31:38 -03002182 dev_info(sport->port.dev, "Serial: Console lpuart rounded baud rate"
Jingchang Luc9e2e942013-06-07 09:20:40 +08002183 "from %d to %d\n", baud_raw, *baud);
2184}
2185
Jingchang Lu380c9662014-07-14 17:41:11 +08002186static void __init
2187lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
2188 int *parity, int *bits)
2189{
2190 unsigned long cr, bd;
2191 unsigned int sbr, uartclk, baud_raw;
2192
Dong Aishenga0204f22017-06-13 10:55:49 +08002193 cr = lpuart32_read(&sport->port, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08002194 cr &= UARTCTRL_TE | UARTCTRL_RE;
2195 if (!cr)
2196 return;
2197
2198 /* ok, the port was enabled */
2199
Dong Aishenga0204f22017-06-13 10:55:49 +08002200 cr = lpuart32_read(&sport->port, UARTCTRL);
Jingchang Lu380c9662014-07-14 17:41:11 +08002201
2202 *parity = 'n';
2203 if (cr & UARTCTRL_PE) {
2204 if (cr & UARTCTRL_PT)
2205 *parity = 'o';
2206 else
2207 *parity = 'e';
2208 }
2209
2210 if (cr & UARTCTRL_M)
2211 *bits = 9;
2212 else
2213 *bits = 8;
2214
Dong Aishenga0204f22017-06-13 10:55:49 +08002215 bd = lpuart32_read(&sport->port, UARTBAUD);
Jingchang Lu380c9662014-07-14 17:41:11 +08002216 bd &= UARTBAUD_SBR_MASK;
2217 sbr = bd;
Fugang Duan35a4ed02019-07-04 21:40:07 +08002218 uartclk = lpuart_get_baud_clk_rate(sport);
Jingchang Lu380c9662014-07-14 17:41:11 +08002219 /*
2220 * baud = mod_clk/(16*(sbr[13]+(brfa)/32)
2221 */
2222 baud_raw = uartclk / (16 * sbr);
2223
2224 if (*baud != baud_raw)
Fabio Estevam9edaf502019-06-04 00:31:38 -03002225 dev_info(sport->port.dev, "Serial: Console lpuart rounded baud rate"
Jingchang Lu380c9662014-07-14 17:41:11 +08002226 "from %d to %d\n", baud_raw, *baud);
2227}
2228
Jingchang Luc9e2e942013-06-07 09:20:40 +08002229static int __init lpuart_console_setup(struct console *co, char *options)
2230{
2231 struct lpuart_port *sport;
2232 int baud = 115200;
2233 int bits = 8;
2234 int parity = 'n';
2235 int flow = 'n';
2236
2237 /*
2238 * check whether an invalid uart number has been specified, and
2239 * if so, search for the first available port that does have
2240 * console support.
2241 */
2242 if (co->index == -1 || co->index >= ARRAY_SIZE(lpuart_ports))
2243 co->index = 0;
2244
2245 sport = lpuart_ports[co->index];
2246 if (sport == NULL)
2247 return -ENODEV;
2248
2249 if (options)
2250 uart_parse_options(options, &baud, &parity, &bits, &flow);
2251 else
Fabio Estevam3ee54472017-07-11 08:03:43 -03002252 if (lpuart_is_32(sport))
Jingchang Lu380c9662014-07-14 17:41:11 +08002253 lpuart32_console_get_options(sport, &baud, &parity, &bits);
2254 else
2255 lpuart_console_get_options(sport, &baud, &parity, &bits);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002256
Fabio Estevam3ee54472017-07-11 08:03:43 -03002257 if (lpuart_is_32(sport))
Jingchang Lu380c9662014-07-14 17:41:11 +08002258 lpuart32_setup_watermark(sport);
2259 else
2260 lpuart_setup_watermark(sport);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002261
2262 return uart_set_options(&sport->port, co, baud, parity, bits, flow);
2263}
2264
2265static struct uart_driver lpuart_reg;
2266static struct console lpuart_console = {
2267 .name = DEV_NAME,
2268 .write = lpuart_console_write,
2269 .device = uart_console_device,
2270 .setup = lpuart_console_setup,
2271 .flags = CON_PRINTBUFFER,
2272 .index = -1,
2273 .data = &lpuart_reg,
2274};
2275
Jingchang Lu380c9662014-07-14 17:41:11 +08002276static struct console lpuart32_console = {
2277 .name = DEV_NAME,
2278 .write = lpuart32_console_write,
2279 .device = uart_console_device,
2280 .setup = lpuart_console_setup,
2281 .flags = CON_PRINTBUFFER,
2282 .index = -1,
2283 .data = &lpuart_reg,
2284};
2285
Stefan Agner1d59b382015-10-17 00:45:55 -07002286static void lpuart_early_write(struct console *con, const char *s, unsigned n)
2287{
2288 struct earlycon_device *dev = con->data;
2289
2290 uart_console_write(&dev->port, s, n, lpuart_console_putchar);
2291}
2292
2293static void lpuart32_early_write(struct console *con, const char *s, unsigned n)
2294{
2295 struct earlycon_device *dev = con->data;
2296
2297 uart_console_write(&dev->port, s, n, lpuart32_console_putchar);
2298}
2299
2300static int __init lpuart_early_console_setup(struct earlycon_device *device,
2301 const char *opt)
2302{
2303 if (!device->port.membase)
2304 return -ENODEV;
2305
2306 device->con->write = lpuart_early_write;
2307 return 0;
2308}
2309
2310static int __init lpuart32_early_console_setup(struct earlycon_device *device,
2311 const char *opt)
2312{
2313 if (!device->port.membase)
2314 return -ENODEV;
2315
Dong Aishengf98e1fc2017-06-13 10:55:50 +08002316 device->port.iotype = UPIO_MEM32BE;
Stefan Agner1d59b382015-10-17 00:45:55 -07002317 device->con->write = lpuart32_early_write;
2318 return 0;
2319}
2320
Dong Aisheng97d6f352017-06-13 10:55:53 +08002321static int __init lpuart32_imx_early_console_setup(struct earlycon_device *device,
2322 const char *opt)
2323{
2324 if (!device->port.membase)
2325 return -ENODEV;
2326
2327 device->port.iotype = UPIO_MEM32;
2328 device->port.membase += IMX_REG_OFF;
2329 device->con->write = lpuart32_early_write;
2330
2331 return 0;
2332}
Stefan Agner1d59b382015-10-17 00:45:55 -07002333OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
2334OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
Dong Aisheng97d6f352017-06-13 10:55:53 +08002335OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
Fugang Duand8a0e922019-07-17 13:19:27 +08002336OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup);
Stefan Agner1d59b382015-10-17 00:45:55 -07002337EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
2338EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
2339
Jingchang Luc9e2e942013-06-07 09:20:40 +08002340#define LPUART_CONSOLE (&lpuart_console)
Jingchang Lu380c9662014-07-14 17:41:11 +08002341#define LPUART32_CONSOLE (&lpuart32_console)
Jingchang Luc9e2e942013-06-07 09:20:40 +08002342#else
2343#define LPUART_CONSOLE NULL
Jingchang Lu380c9662014-07-14 17:41:11 +08002344#define LPUART32_CONSOLE NULL
Jingchang Luc9e2e942013-06-07 09:20:40 +08002345#endif
2346
2347static struct uart_driver lpuart_reg = {
2348 .owner = THIS_MODULE,
2349 .driver_name = DRIVER_NAME,
2350 .dev_name = DEV_NAME,
2351 .nr = ARRAY_SIZE(lpuart_ports),
2352 .cons = LPUART_CONSOLE,
2353};
2354
2355static int lpuart_probe(struct platform_device *pdev)
2356{
Dong Aisheng0d6fce92017-06-13 10:55:48 +08002357 const struct of_device_id *of_id = of_match_device(lpuart_dt_ids,
2358 &pdev->dev);
2359 const struct lpuart_soc_data *sdata = of_id->data;
Jingchang Luc9e2e942013-06-07 09:20:40 +08002360 struct device_node *np = pdev->dev.of_node;
2361 struct lpuart_port *sport;
2362 struct resource *res;
2363 int ret;
2364
2365 sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
2366 if (!sport)
2367 return -ENOMEM;
2368
Jingchang Luc9e2e942013-06-07 09:20:40 +08002369 ret = of_alias_get_id(np, "serial");
2370 if (ret < 0) {
Vabhav Sharma3bc32062018-10-10 03:56:16 +05302371 ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
2372 if (ret < 0) {
2373 dev_err(&pdev->dev, "port line is full, add device failed\n");
2374 return ret;
2375 }
Jingchang Luc9e2e942013-06-07 09:20:40 +08002376 }
Geert Uytterhoevenffab87f2018-02-23 14:38:30 +01002377 if (ret >= ARRAY_SIZE(lpuart_ports)) {
2378 dev_err(&pdev->dev, "serial%d out of range\n", ret);
2379 return -EINVAL;
2380 }
Jingchang Luc9e2e942013-06-07 09:20:40 +08002381 sport->port.line = ret;
Fabio Estevam4ae612a2014-11-07 00:23:13 -02002382 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002383 sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
2384 if (IS_ERR(sport->port.membase))
2385 return PTR_ERR(sport->port.membase);
2386
Dong Aisheng24b1e5f2017-06-13 10:55:52 +08002387 sport->port.membase += sdata->reg_off;
Fabio Estevam4ae612a2014-11-07 00:23:13 -02002388 sport->port.mapbase = res->start;
Jingchang Luc9e2e942013-06-07 09:20:40 +08002389 sport->port.dev = &pdev->dev;
2390 sport->port.type = PORT_LPUART;
Fugang Duan35a4ed02019-07-04 21:40:07 +08002391 sport->devtype = sdata->devtype;
Jiri Slaby394a9e22016-05-09 09:23:35 +02002392 ret = platform_get_irq(pdev, 0);
2393 if (ret < 0) {
2394 dev_err(&pdev->dev, "cannot obtain irq\n");
2395 return ret;
2396 }
2397 sport->port.irq = ret;
Dong Aisheng0d6fce92017-06-13 10:55:48 +08002398 sport->port.iotype = sdata->iotype;
Fabio Estevam3ee54472017-07-11 08:03:43 -03002399 if (lpuart_is_32(sport))
Jingchang Lu380c9662014-07-14 17:41:11 +08002400 sport->port.ops = &lpuart32_pops;
2401 else
2402 sport->port.ops = &lpuart_pops;
Jingchang Luc9e2e942013-06-07 09:20:40 +08002403 sport->port.flags = UPF_BOOT_AUTOCONF;
2404
Bhuvanchandra DV03895cf2016-07-19 13:13:10 +05302405 sport->port.rs485_config = lpuart_config_rs485;
2406
Fugang Duan35a4ed02019-07-04 21:40:07 +08002407 sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
2408 if (IS_ERR(sport->ipg_clk)) {
2409 ret = PTR_ERR(sport->ipg_clk);
2410 dev_err(&pdev->dev, "failed to get uart ipg clk: %d\n", ret);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002411 return ret;
2412 }
2413
Fugang Duan35a4ed02019-07-04 21:40:07 +08002414 sport->baud_clk = NULL;
2415 if (is_imx8qxp_lpuart(sport)) {
2416 sport->baud_clk = devm_clk_get(&pdev->dev, "baud");
2417 if (IS_ERR(sport->baud_clk)) {
2418 ret = PTR_ERR(sport->baud_clk);
2419 dev_err(&pdev->dev, "failed to get uart baud clk: %d\n", ret);
2420 return ret;
2421 }
Jingchang Luc9e2e942013-06-07 09:20:40 +08002422 }
2423
Fugang Duan35a4ed02019-07-04 21:40:07 +08002424 ret = lpuart_enable_clks(sport);
2425 if (ret)
2426 return ret;
2427 sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002428
2429 lpuart_ports[sport->port.line] = sport;
2430
2431 platform_set_drvdata(pdev, &sport->port);
2432
Fugang Duan9d7ee0e2017-09-04 19:20:24 +08002433 if (lpuart_is_32(sport)) {
Jingchang Lu380c9662014-07-14 17:41:11 +08002434 lpuart_reg.cons = LPUART32_CONSOLE;
Fugang Duan9d7ee0e2017-09-04 19:20:24 +08002435 ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0,
2436 DRIVER_NAME, sport);
2437 } else {
Jingchang Lu380c9662014-07-14 17:41:11 +08002438 lpuart_reg.cons = LPUART_CONSOLE;
Fugang Duan9d7ee0e2017-09-04 19:20:24 +08002439 ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0,
2440 DRIVER_NAME, sport);
2441 }
2442
2443 if (ret)
2444 goto failed_irq_request;
Jingchang Lu380c9662014-07-14 17:41:11 +08002445
Jingchang Luc9e2e942013-06-07 09:20:40 +08002446 ret = uart_add_one_port(&lpuart_reg, &sport->port);
Fugang Duan9d7ee0e2017-09-04 19:20:24 +08002447 if (ret)
2448 goto failed_attach_port;
Jingchang Luc9e2e942013-06-07 09:20:40 +08002449
Lukas Wunner743f93f2017-11-24 23:26:40 +01002450 uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
Sascha Hauerdde18d52017-09-13 10:18:29 +02002451
Lukas Wunner01d84532017-11-24 23:26:40 +01002452 if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX)
Sascha Hauerdde18d52017-09-13 10:18:29 +02002453 dev_err(&pdev->dev, "driver doesn't support RX during TX\n");
Sascha Hauerdde18d52017-09-13 10:18:29 +02002454
2455 if (sport->port.rs485.delay_rts_before_send ||
Lukas Wunner01d84532017-11-24 23:26:40 +01002456 sport->port.rs485.delay_rts_after_send)
Sascha Hauerdde18d52017-09-13 10:18:29 +02002457 dev_err(&pdev->dev, "driver doesn't support RTS delays\n");
Sascha Hauerdde18d52017-09-13 10:18:29 +02002458
Lukas Wunner01d84532017-11-24 23:26:40 +01002459 lpuart_config_rs485(&sport->port, &sport->port.rs485);
Sascha Hauerdde18d52017-09-13 10:18:29 +02002460
Stefan Agner4a818c42015-01-10 09:33:45 +01002461 sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
2462 if (!sport->dma_tx_chan)
2463 dev_info(sport->port.dev, "DMA tx channel request failed, "
2464 "operating without tx DMA\n");
2465
2466 sport->dma_rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
2467 if (!sport->dma_rx_chan)
2468 dev_info(sport->port.dev, "DMA rx channel request failed, "
2469 "operating without rx DMA\n");
2470
Jingchang Luc9e2e942013-06-07 09:20:40 +08002471 return 0;
Fugang Duan9d7ee0e2017-09-04 19:20:24 +08002472
2473failed_attach_port:
2474failed_irq_request:
Fugang Duan35a4ed02019-07-04 21:40:07 +08002475 lpuart_disable_clks(sport);
Fugang Duan9d7ee0e2017-09-04 19:20:24 +08002476 return ret;
Jingchang Luc9e2e942013-06-07 09:20:40 +08002477}
2478
2479static int lpuart_remove(struct platform_device *pdev)
2480{
2481 struct lpuart_port *sport = platform_get_drvdata(pdev);
2482
2483 uart_remove_one_port(&lpuart_reg, &sport->port);
2484
Vabhav Sharma3bc32062018-10-10 03:56:16 +05302485 ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
2486
Fugang Duan35a4ed02019-07-04 21:40:07 +08002487 lpuart_disable_clks(sport);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002488
Stefan Agner4a818c42015-01-10 09:33:45 +01002489 if (sport->dma_tx_chan)
2490 dma_release_channel(sport->dma_tx_chan);
2491
2492 if (sport->dma_rx_chan)
2493 dma_release_channel(sport->dma_rx_chan);
2494
Jingchang Luc9e2e942013-06-07 09:20:40 +08002495 return 0;
2496}
2497
2498#ifdef CONFIG_PM_SLEEP
2499static int lpuart_suspend(struct device *dev)
2500{
2501 struct lpuart_port *sport = dev_get_drvdata(dev);
Yuan Yao2fe605d2015-01-23 17:48:54 +08002502 unsigned long temp;
Andy Shevchenko3d6bcdd2017-08-13 17:47:39 +03002503 bool irq_wake;
Yuan Yao2fe605d2015-01-23 17:48:54 +08002504
Fabio Estevam3ee54472017-07-11 08:03:43 -03002505 if (lpuart_is_32(sport)) {
Yuan Yao2fe605d2015-01-23 17:48:54 +08002506 /* disable Rx/Tx and interrupts */
Dong Aishenga0204f22017-06-13 10:55:49 +08002507 temp = lpuart32_read(&sport->port, UARTCTRL);
Yuan Yao2fe605d2015-01-23 17:48:54 +08002508 temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE);
Dong Aishenga0204f22017-06-13 10:55:49 +08002509 lpuart32_write(&sport->port, temp, UARTCTRL);
Yuan Yao2fe605d2015-01-23 17:48:54 +08002510 } else {
2511 /* disable Rx/Tx and interrupts */
2512 temp = readb(sport->port.membase + UARTCR2);
2513 temp &= ~(UARTCR2_TE | UARTCR2_TIE | UARTCR2_TCIE);
2514 writeb(temp, sport->port.membase + UARTCR2);
2515 }
Jingchang Luc9e2e942013-06-07 09:20:40 +08002516
2517 uart_suspend_port(&lpuart_reg, &sport->port);
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302518
Andy Shevchenko3d6bcdd2017-08-13 17:47:39 +03002519 /* uart_suspend_port() might set wakeup flag */
2520 irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
2521
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302522 if (sport->lpuart_dma_rx_use) {
2523 /*
2524 * EDMA driver during suspend will forcefully release any
2525 * non-idle DMA channels. If port wakeup is enabled or if port
2526 * is console port or 'no_console_suspend' is set the Rx DMA
2527 * cannot resume as as expected, hence gracefully release the
2528 * Rx DMA path before suspend and start Rx DMA path on resume.
2529 */
Andy Shevchenko3d6bcdd2017-08-13 17:47:39 +03002530 if (irq_wake) {
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302531 del_timer_sync(&sport->lpuart_timer);
2532 lpuart_dma_rx_free(&sport->port);
2533 }
2534
2535 /* Disable Rx DMA to use UART port as wakeup source */
Atsushi Nemoto42b68762019-01-23 12:20:17 +09002536 if (lpuart_is_32(sport)) {
2537 temp = lpuart32_read(&sport->port, UARTBAUD);
2538 lpuart32_write(&sport->port, temp & ~UARTBAUD_RDMAE,
2539 UARTBAUD);
2540 } else {
2541 writeb(readb(sport->port.membase + UARTCR5) &
2542 ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
2543 }
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302544 }
2545
2546 if (sport->lpuart_dma_tx_use) {
2547 sport->dma_tx_in_progress = false;
2548 dmaengine_terminate_all(sport->dma_tx_chan);
2549 }
2550
Andy Shevchenko3d6bcdd2017-08-13 17:47:39 +03002551 if (sport->port.suspended && !irq_wake)
Fugang Duan35a4ed02019-07-04 21:40:07 +08002552 lpuart_disable_clks(sport);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002553
2554 return 0;
2555}
2556
2557static int lpuart_resume(struct device *dev)
2558{
2559 struct lpuart_port *sport = dev_get_drvdata(dev);
Andy Shevchenko3d6bcdd2017-08-13 17:47:39 +03002560 bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
Jingchang Lu08de1012014-10-24 17:20:49 +08002561 unsigned long temp;
2562
Andy Shevchenko3d6bcdd2017-08-13 17:47:39 +03002563 if (sport->port.suspended && !irq_wake)
Fugang Duan35a4ed02019-07-04 21:40:07 +08002564 lpuart_enable_clks(sport);
Stefan Agnerd6b0d2f2016-07-19 13:13:04 +05302565
Fabio Estevam3ee54472017-07-11 08:03:43 -03002566 if (lpuart_is_32(sport)) {
Jingchang Lu08de1012014-10-24 17:20:49 +08002567 lpuart32_setup_watermark(sport);
Dong Aishenga0204f22017-06-13 10:55:49 +08002568 temp = lpuart32_read(&sport->port, UARTCTRL);
Atsushi Nemoto42b68762019-01-23 12:20:17 +09002569 temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
Dong Aishenga0204f22017-06-13 10:55:49 +08002570 lpuart32_write(&sport->port, temp, UARTCTRL);
Jingchang Lu08de1012014-10-24 17:20:49 +08002571 } else {
2572 lpuart_setup_watermark(sport);
2573 temp = readb(sport->port.membase + UARTCR2);
Andrey Smirnovbcfa46b2019-07-29 12:52:13 -07002574 temp |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
Jingchang Lu08de1012014-10-24 17:20:49 +08002575 writeb(temp, sport->port.membase + UARTCR2);
2576 }
Jingchang Luc9e2e942013-06-07 09:20:40 +08002577
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302578 if (sport->lpuart_dma_rx_use) {
Andy Shevchenko3d6bcdd2017-08-13 17:47:39 +03002579 if (irq_wake) {
Nikita Yushchenko54a44d52016-12-04 18:49:28 +03002580 if (!lpuart_start_rx_dma(sport))
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302581 rx_dma_timer_init(sport);
Nikita Yushchenko54a44d52016-12-04 18:49:28 +03002582 else
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302583 sport->lpuart_dma_rx_use = false;
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302584 }
2585 }
2586
2587 if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) {
Atsushi Nemoto42b68762019-01-23 12:20:17 +09002588 init_waitqueue_head(&sport->dma_wait);
2589 sport->lpuart_dma_tx_use = true;
2590 if (lpuart_is_32(sport)) {
2591 temp = lpuart32_read(&sport->port, UARTBAUD);
2592 lpuart32_write(&sport->port,
2593 temp | UARTBAUD_TDMAE, UARTBAUD);
2594 } else {
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302595 writeb(readb(sport->port.membase + UARTCR5) |
2596 UARTCR5_TDMAS, sport->port.membase + UARTCR5);
Atsushi Nemoto42b68762019-01-23 12:20:17 +09002597 }
Bhuvanchandra DVc05efd62016-07-19 13:13:09 +05302598 } else {
2599 sport->lpuart_dma_tx_use = false;
2600 }
2601
Atsushi Nemoto42b68762019-01-23 12:20:17 +09002602 if (lpuart_is_32(sport)) {
2603 if (sport->lpuart_dma_rx_use) {
2604 /* RXWATER must be 0 */
2605 temp = lpuart32_read(&sport->port, UARTWATER);
2606 temp &= ~(UARTWATER_WATER_MASK <<
2607 UARTWATER_RXWATER_OFF);
2608 lpuart32_write(&sport->port, temp, UARTWATER);
2609 }
2610 temp = lpuart32_read(&sport->port, UARTCTRL);
2611 if (!sport->lpuart_dma_rx_use)
2612 temp |= UARTCTRL_RIE;
2613 if (!sport->lpuart_dma_tx_use)
2614 temp |= UARTCTRL_TIE;
2615 lpuart32_write(&sport->port, temp, UARTCTRL);
2616 }
2617
Jingchang Luc9e2e942013-06-07 09:20:40 +08002618 uart_resume_port(&lpuart_reg, &sport->port);
2619
2620 return 0;
2621}
2622#endif
2623
2624static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume);
2625
2626static struct platform_driver lpuart_driver = {
2627 .probe = lpuart_probe,
2628 .remove = lpuart_remove,
2629 .driver = {
2630 .name = "fsl-lpuart",
Jingchang Luc9e2e942013-06-07 09:20:40 +08002631 .of_match_table = lpuart_dt_ids,
2632 .pm = &lpuart_pm_ops,
2633 },
2634};
2635
2636static int __init lpuart_serial_init(void)
2637{
Fabio Estevam144c29e2014-11-07 00:23:14 -02002638 int ret = uart_register_driver(&lpuart_reg);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002639
Jingchang Luc9e2e942013-06-07 09:20:40 +08002640 if (ret)
2641 return ret;
2642
2643 ret = platform_driver_register(&lpuart_driver);
2644 if (ret)
2645 uart_unregister_driver(&lpuart_reg);
2646
Axel Lin39c34b02013-07-22 09:12:36 +08002647 return ret;
Jingchang Luc9e2e942013-06-07 09:20:40 +08002648}
2649
2650static void __exit lpuart_serial_exit(void)
2651{
Vabhav Sharma3bc32062018-10-10 03:56:16 +05302652 ida_destroy(&fsl_lpuart_ida);
Jingchang Luc9e2e942013-06-07 09:20:40 +08002653 platform_driver_unregister(&lpuart_driver);
2654 uart_unregister_driver(&lpuart_reg);
2655}
2656
2657module_init(lpuart_serial_init);
2658module_exit(lpuart_serial_exit);
2659
2660MODULE_DESCRIPTION("Freescale lpuart serial port driver");
2661MODULE_LICENSE("GPL v2");