blob: f0351e6f0ef6d44ba6d6615ad5e99abcf7abd1ef [file] [log] [blame]
Greg Kroah-Hartmane3b3d0f2017-11-06 18:11:51 +01001// SPDX-License-Identifier: GPL-2.0
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09002/*
Tomoya MORINAGAeca9dfa2011-10-28 09:38:50 +09003 *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09004 */
Uwe Kleine-König0e2adc02011-05-26 10:41:17 +02005#include <linux/kernel.h>
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09006#include <linux/serial_reg.h>
Andrew Morton023bc8e2011-05-24 17:13:44 -07007#include <linux/slab.h>
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09008#include <linux/module.h>
9#include <linux/pci.h>
Liang Li1f9db092013-01-19 17:52:11 +080010#include <linux/console.h>
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090011#include <linux/serial_core.h>
Jiri Slabyee160a32011-09-01 16:20:57 +020012#include <linux/tty.h>
13#include <linux/tty_flip.h>
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090014#include <linux/interrupt.h>
15#include <linux/io.h>
Denis Turischev6ae705b2011-03-10 15:14:00 +020016#include <linux/dmi.h>
Alexander Steine30f8672011-11-15 15:04:07 -080017#include <linux/nmi.h>
18#include <linux/delay.h>
Zubair Lutfullah Kakakhel7789e5a2016-08-12 12:48:54 +010019#include <linux/of.h>
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090020
Feng Tangd0114112012-02-06 17:24:43 +080021#include <linux/debugfs.h>
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090022#include <linux/dmaengine.h>
23#include <linux/pch_dma.h>
24
25enum {
26 PCH_UART_HANDLED_RX_INT_SHIFT,
27 PCH_UART_HANDLED_TX_INT_SHIFT,
28 PCH_UART_HANDLED_RX_ERR_INT_SHIFT,
29 PCH_UART_HANDLED_RX_TRG_INT_SHIFT,
30 PCH_UART_HANDLED_MS_INT_SHIFT,
Tomoya MORINAGA04e2c2e2012-03-26 14:43:05 +090031 PCH_UART_HANDLED_LS_INT_SHIFT,
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090032};
33
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090034#define PCH_UART_DRIVER_DEVICE "ttyPCH"
35
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +090036/* Set the max number of UART port
37 * Intel EG20T PCH: 4 port
Tomoya MORINAGAeca9dfa2011-10-28 09:38:50 +090038 * LAPIS Semiconductor ML7213 IOH: 3 port
39 * LAPIS Semiconductor ML7223 IOH: 2 port
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +090040*/
41#define PCH_UART_NR 4
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090042
43#define PCH_UART_HANDLED_RX_INT (1<<((PCH_UART_HANDLED_RX_INT_SHIFT)<<1))
44#define PCH_UART_HANDLED_TX_INT (1<<((PCH_UART_HANDLED_TX_INT_SHIFT)<<1))
45#define PCH_UART_HANDLED_RX_ERR_INT (1<<((\
46 PCH_UART_HANDLED_RX_ERR_INT_SHIFT)<<1))
47#define PCH_UART_HANDLED_RX_TRG_INT (1<<((\
48 PCH_UART_HANDLED_RX_TRG_INT_SHIFT)<<1))
49#define PCH_UART_HANDLED_MS_INT (1<<((PCH_UART_HANDLED_MS_INT_SHIFT)<<1))
50
Tomoya MORINAGA04e2c2e2012-03-26 14:43:05 +090051#define PCH_UART_HANDLED_LS_INT (1<<((PCH_UART_HANDLED_LS_INT_SHIFT)<<1))
52
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +090053#define PCH_UART_RBR 0x00
54#define PCH_UART_THR 0x00
55
56#define PCH_UART_IER_MASK (PCH_UART_IER_ERBFI|PCH_UART_IER_ETBEI|\
57 PCH_UART_IER_ELSI|PCH_UART_IER_EDSSI)
58#define PCH_UART_IER_ERBFI 0x00000001
59#define PCH_UART_IER_ETBEI 0x00000002
60#define PCH_UART_IER_ELSI 0x00000004
61#define PCH_UART_IER_EDSSI 0x00000008
62
63#define PCH_UART_IIR_IP 0x00000001
64#define PCH_UART_IIR_IID 0x00000006
65#define PCH_UART_IIR_MSI 0x00000000
66#define PCH_UART_IIR_TRI 0x00000002
67#define PCH_UART_IIR_RRI 0x00000004
68#define PCH_UART_IIR_REI 0x00000006
69#define PCH_UART_IIR_TOI 0x00000008
70#define PCH_UART_IIR_FIFO256 0x00000020
71#define PCH_UART_IIR_FIFO64 PCH_UART_IIR_FIFO256
72#define PCH_UART_IIR_FE 0x000000C0
73
74#define PCH_UART_FCR_FIFOE 0x00000001
75#define PCH_UART_FCR_RFR 0x00000002
76#define PCH_UART_FCR_TFR 0x00000004
77#define PCH_UART_FCR_DMS 0x00000008
78#define PCH_UART_FCR_FIFO256 0x00000020
79#define PCH_UART_FCR_RFTL 0x000000C0
80
81#define PCH_UART_FCR_RFTL1 0x00000000
82#define PCH_UART_FCR_RFTL64 0x00000040
83#define PCH_UART_FCR_RFTL128 0x00000080
84#define PCH_UART_FCR_RFTL224 0x000000C0
85#define PCH_UART_FCR_RFTL16 PCH_UART_FCR_RFTL64
86#define PCH_UART_FCR_RFTL32 PCH_UART_FCR_RFTL128
87#define PCH_UART_FCR_RFTL56 PCH_UART_FCR_RFTL224
88#define PCH_UART_FCR_RFTL4 PCH_UART_FCR_RFTL64
89#define PCH_UART_FCR_RFTL8 PCH_UART_FCR_RFTL128
90#define PCH_UART_FCR_RFTL14 PCH_UART_FCR_RFTL224
91#define PCH_UART_FCR_RFTL_SHIFT 6
92
93#define PCH_UART_LCR_WLS 0x00000003
94#define PCH_UART_LCR_STB 0x00000004
95#define PCH_UART_LCR_PEN 0x00000008
96#define PCH_UART_LCR_EPS 0x00000010
97#define PCH_UART_LCR_SP 0x00000020
98#define PCH_UART_LCR_SB 0x00000040
99#define PCH_UART_LCR_DLAB 0x00000080
100#define PCH_UART_LCR_NP 0x00000000
101#define PCH_UART_LCR_OP PCH_UART_LCR_PEN
102#define PCH_UART_LCR_EP (PCH_UART_LCR_PEN | PCH_UART_LCR_EPS)
103#define PCH_UART_LCR_1P (PCH_UART_LCR_PEN | PCH_UART_LCR_SP)
104#define PCH_UART_LCR_0P (PCH_UART_LCR_PEN | PCH_UART_LCR_EPS |\
105 PCH_UART_LCR_SP)
106
107#define PCH_UART_LCR_5BIT 0x00000000
108#define PCH_UART_LCR_6BIT 0x00000001
109#define PCH_UART_LCR_7BIT 0x00000002
110#define PCH_UART_LCR_8BIT 0x00000003
111
112#define PCH_UART_MCR_DTR 0x00000001
113#define PCH_UART_MCR_RTS 0x00000002
114#define PCH_UART_MCR_OUT 0x0000000C
115#define PCH_UART_MCR_LOOP 0x00000010
116#define PCH_UART_MCR_AFE 0x00000020
117
118#define PCH_UART_LSR_DR 0x00000001
119#define PCH_UART_LSR_ERR (1<<7)
120
121#define PCH_UART_MSR_DCTS 0x00000001
122#define PCH_UART_MSR_DDSR 0x00000002
123#define PCH_UART_MSR_TERI 0x00000004
124#define PCH_UART_MSR_DDCD 0x00000008
125#define PCH_UART_MSR_CTS 0x00000010
126#define PCH_UART_MSR_DSR 0x00000020
127#define PCH_UART_MSR_RI 0x00000040
128#define PCH_UART_MSR_DCD 0x00000080
129#define PCH_UART_MSR_DELTA (PCH_UART_MSR_DCTS | PCH_UART_MSR_DDSR |\
130 PCH_UART_MSR_TERI | PCH_UART_MSR_DDCD)
131
132#define PCH_UART_DLL 0x00
133#define PCH_UART_DLM 0x01
134
Feng Tangd0114112012-02-06 17:24:43 +0800135#define PCH_UART_BRCSR 0x0E
136
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900137#define PCH_UART_IID_RLS (PCH_UART_IIR_REI)
138#define PCH_UART_IID_RDR (PCH_UART_IIR_RRI)
139#define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI)
140#define PCH_UART_IID_THRE (PCH_UART_IIR_TRI)
141#define PCH_UART_IID_MS (PCH_UART_IIR_MSI)
142
143#define PCH_UART_HAL_PARITY_NONE (PCH_UART_LCR_NP)
144#define PCH_UART_HAL_PARITY_ODD (PCH_UART_LCR_OP)
145#define PCH_UART_HAL_PARITY_EVEN (PCH_UART_LCR_EP)
146#define PCH_UART_HAL_PARITY_FIX1 (PCH_UART_LCR_1P)
147#define PCH_UART_HAL_PARITY_FIX0 (PCH_UART_LCR_0P)
148#define PCH_UART_HAL_5BIT (PCH_UART_LCR_5BIT)
149#define PCH_UART_HAL_6BIT (PCH_UART_LCR_6BIT)
150#define PCH_UART_HAL_7BIT (PCH_UART_LCR_7BIT)
151#define PCH_UART_HAL_8BIT (PCH_UART_LCR_8BIT)
152#define PCH_UART_HAL_STB1 0
153#define PCH_UART_HAL_STB2 (PCH_UART_LCR_STB)
154
155#define PCH_UART_HAL_CLR_TX_FIFO (PCH_UART_FCR_TFR)
156#define PCH_UART_HAL_CLR_RX_FIFO (PCH_UART_FCR_RFR)
157#define PCH_UART_HAL_CLR_ALL_FIFO (PCH_UART_HAL_CLR_TX_FIFO | \
158 PCH_UART_HAL_CLR_RX_FIFO)
159
160#define PCH_UART_HAL_DMA_MODE0 0
161#define PCH_UART_HAL_FIFO_DIS 0
162#define PCH_UART_HAL_FIFO16 (PCH_UART_FCR_FIFOE)
163#define PCH_UART_HAL_FIFO256 (PCH_UART_FCR_FIFOE | \
164 PCH_UART_FCR_FIFO256)
165#define PCH_UART_HAL_FIFO64 (PCH_UART_HAL_FIFO256)
166#define PCH_UART_HAL_TRIGGER1 (PCH_UART_FCR_RFTL1)
167#define PCH_UART_HAL_TRIGGER64 (PCH_UART_FCR_RFTL64)
168#define PCH_UART_HAL_TRIGGER128 (PCH_UART_FCR_RFTL128)
169#define PCH_UART_HAL_TRIGGER224 (PCH_UART_FCR_RFTL224)
170#define PCH_UART_HAL_TRIGGER16 (PCH_UART_FCR_RFTL16)
171#define PCH_UART_HAL_TRIGGER32 (PCH_UART_FCR_RFTL32)
172#define PCH_UART_HAL_TRIGGER56 (PCH_UART_FCR_RFTL56)
173#define PCH_UART_HAL_TRIGGER4 (PCH_UART_FCR_RFTL4)
174#define PCH_UART_HAL_TRIGGER8 (PCH_UART_FCR_RFTL8)
175#define PCH_UART_HAL_TRIGGER14 (PCH_UART_FCR_RFTL14)
176#define PCH_UART_HAL_TRIGGER_L (PCH_UART_FCR_RFTL64)
177#define PCH_UART_HAL_TRIGGER_M (PCH_UART_FCR_RFTL128)
178#define PCH_UART_HAL_TRIGGER_H (PCH_UART_FCR_RFTL224)
179
180#define PCH_UART_HAL_RX_INT (PCH_UART_IER_ERBFI)
181#define PCH_UART_HAL_TX_INT (PCH_UART_IER_ETBEI)
182#define PCH_UART_HAL_RX_ERR_INT (PCH_UART_IER_ELSI)
183#define PCH_UART_HAL_MS_INT (PCH_UART_IER_EDSSI)
184#define PCH_UART_HAL_ALL_INT (PCH_UART_IER_MASK)
185
186#define PCH_UART_HAL_DTR (PCH_UART_MCR_DTR)
187#define PCH_UART_HAL_RTS (PCH_UART_MCR_RTS)
188#define PCH_UART_HAL_OUT (PCH_UART_MCR_OUT)
189#define PCH_UART_HAL_LOOP (PCH_UART_MCR_LOOP)
190#define PCH_UART_HAL_AFE (PCH_UART_MCR_AFE)
191
Alexander Steine30f8672011-11-15 15:04:07 -0800192#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
193
Darren Hart077175f2012-03-09 09:51:49 -0800194#define DEFAULT_UARTCLK 1843200 /* 1.8432 MHz */
195#define CMITC_UARTCLK 192000000 /* 192.0000 MHz */
196#define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */
197#define FRI2_48_UARTCLK 48000000 /* 48.0000 MHz */
Michael Brunner11bbd5b2012-03-23 11:06:37 +0100198#define NTC1_UARTCLK 64000000 /* 64.0000 MHz */
Darren Hart29692d02013-06-25 18:53:22 -0700199#define MINNOW_UARTCLK 50000000 /* 50.0000 MHz */
Alexander Steine30f8672011-11-15 15:04:07 -0800200
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900201struct pch_uart_buffer {
202 unsigned char *buf;
203 int size;
204};
205
206struct eg20t_port {
207 struct uart_port port;
208 int port_type;
209 void __iomem *membase;
210 resource_size_t mapbase;
211 unsigned int iobase;
212 struct pci_dev *pdev;
213 int fifo_size;
Darren Harte26439c2013-07-29 15:15:07 -0700214 unsigned int uartclk;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900215 int start_tx;
216 int start_rx;
217 int tx_empty;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900218 int trigger;
219 int trigger_level;
220 struct pch_uart_buffer rxbuf;
221 unsigned int dmsr;
222 unsigned int fcr;
Tomoya MORINAGA9af71552011-02-23 10:03:17 +0900223 unsigned int mcr;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900224 unsigned int use_dma;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900225 struct dma_async_tx_descriptor *desc_tx;
226 struct dma_async_tx_descriptor *desc_rx;
227 struct pch_dma_slave param_tx;
228 struct pch_dma_slave param_rx;
229 struct dma_chan *chan_tx;
230 struct dma_chan *chan_rx;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900231 struct scatterlist *sg_tx_p;
232 int nent;
Peng Fan74887542019-11-13 05:37:42 +0000233 int orig_nent;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900234 struct scatterlist sg_rx;
235 int tx_dma_use;
236 void *rx_buf_virt;
237 dma_addr_t rx_buf_dma;
Feng Tangd0114112012-02-06 17:24:43 +0800238
Alexander Stein50d16ca2014-03-25 14:05:08 +0100239#define IRQ_NAME_SIZE 17
240 char irq_name[IRQ_NAME_SIZE];
Darren Hartfe89def2012-06-19 14:00:18 -0700241
242 /* protect the eg20t_port private structure and io access to membase */
243 spinlock_t lock;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900244};
245
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +0900246/**
247 * struct pch_uart_driver_data - private data structure for UART-DMA
Andy Shevchenko63e8d432017-08-22 16:58:20 +0300248 * @port_type: The type of UART port
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +0900249 * @line_no: UART port line number (0, 1, 2...)
250 */
251struct pch_uart_driver_data {
252 int port_type;
253 int line_no;
254};
255
256enum pch_uart_num_t {
257 pch_et20t_uart0 = 0,
258 pch_et20t_uart1,
259 pch_et20t_uart2,
260 pch_et20t_uart3,
261 pch_ml7213_uart0,
262 pch_ml7213_uart1,
263 pch_ml7213_uart2,
Tomoya MORINAGA177c2cb2011-05-09 17:25:20 +0900264 pch_ml7223_uart0,
265 pch_ml7223_uart1,
Tomoya MORINAGA8249f742011-10-28 09:38:49 +0900266 pch_ml7831_uart0,
267 pch_ml7831_uart1,
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +0900268};
269
270static struct pch_uart_driver_data drv_dat[] = {
Andy Shevchenko63e8d432017-08-22 16:58:20 +0300271 [pch_et20t_uart0] = {PORT_PCH_8LINE, 0},
272 [pch_et20t_uart1] = {PORT_PCH_2LINE, 1},
273 [pch_et20t_uart2] = {PORT_PCH_2LINE, 2},
274 [pch_et20t_uart3] = {PORT_PCH_2LINE, 3},
275 [pch_ml7213_uart0] = {PORT_PCH_8LINE, 0},
276 [pch_ml7213_uart1] = {PORT_PCH_2LINE, 1},
277 [pch_ml7213_uart2] = {PORT_PCH_2LINE, 2},
278 [pch_ml7223_uart0] = {PORT_PCH_8LINE, 0},
279 [pch_ml7223_uart1] = {PORT_PCH_2LINE, 1},
280 [pch_ml7831_uart0] = {PORT_PCH_8LINE, 0},
281 [pch_ml7831_uart1] = {PORT_PCH_2LINE, 1},
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +0900282};
283
Alexander Steine30f8672011-11-15 15:04:07 -0800284#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
285static struct eg20t_port *pch_uart_ports[PCH_UART_NR];
286#endif
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900287static unsigned int default_baud = 9600;
Darren Hart2a44feb2012-03-09 09:51:50 -0800288static unsigned int user_uartclk = 0;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900289static const int trigger_level_256[4] = { 1, 64, 128, 224 };
290static const int trigger_level_64[4] = { 1, 16, 32, 56 };
291static const int trigger_level_16[4] = { 1, 4, 8, 14 };
292static const int trigger_level_1[4] = { 1, 1, 1, 1 };
293
Feng Tangd0114112012-02-06 17:24:43 +0800294#define PCH_REGS_BUFSIZE 1024
Stephen Boyd234e3402012-04-05 14:25:11 -0700295
Feng Tangd0114112012-02-06 17:24:43 +0800296
297static ssize_t port_show_regs(struct file *file, char __user *user_buf,
298 size_t count, loff_t *ppos)
299{
300 struct eg20t_port *priv = file->private_data;
301 char *buf;
302 u32 len = 0;
303 ssize_t ret;
304 unsigned char lcr;
305
306 buf = kzalloc(PCH_REGS_BUFSIZE, GFP_KERNEL);
307 if (!buf)
308 return 0;
309
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100310 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800311 "PCH EG20T port[%d] regs:\n", priv->port.line);
312
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100313 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800314 "=================================\n");
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100315 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800316 "IER: \t0x%02x\n", ioread8(priv->membase + UART_IER));
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100317 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800318 "IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR));
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100319 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800320 "LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR));
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100321 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800322 "MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR));
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100323 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800324 "LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR));
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100325 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800326 "MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR));
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100327 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800328 "BRCSR: \t0x%02x\n",
329 ioread8(priv->membase + PCH_UART_BRCSR));
330
331 lcr = ioread8(priv->membase + UART_LCR);
332 iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100333 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800334 "DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL));
Takashi Iwaie39c0ff2020-03-11 10:29:30 +0100335 len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
Feng Tangd0114112012-02-06 17:24:43 +0800336 "DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM));
337 iowrite8(lcr, priv->membase + UART_LCR);
338
339 if (len > PCH_REGS_BUFSIZE)
340 len = PCH_REGS_BUFSIZE;
341
342 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
343 kfree(buf);
344 return ret;
345}
346
347static const struct file_operations port_regs_ops = {
348 .owner = THIS_MODULE,
Stephen Boyd234e3402012-04-05 14:25:11 -0700349 .open = simple_open,
Feng Tangd0114112012-02-06 17:24:43 +0800350 .read = port_show_regs,
351 .llseek = default_llseek,
352};
Feng Tangd0114112012-02-06 17:24:43 +0800353
Christoph Hellwig6faadbb2017-09-14 11:59:30 +0200354static const struct dmi_system_id pch_uart_dmi_table[] = {
Darren Hart4e3234892013-07-12 17:58:05 -0700355 {
356 .ident = "CM-iTC",
357 {
358 DMI_MATCH(DMI_BOARD_NAME, "CM-iTC"),
359 },
360 (void *)CMITC_UARTCLK,
361 },
362 {
363 .ident = "FRI2",
364 {
365 DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
366 },
367 (void *)FRI2_64_UARTCLK,
368 },
369 {
370 .ident = "Fish River Island II",
371 {
372 DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
373 },
374 (void *)FRI2_48_UARTCLK,
375 },
376 {
377 .ident = "COMe-mTT",
378 {
379 DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
380 },
381 (void *)NTC1_UARTCLK,
382 },
383 {
384 .ident = "nanoETXexpress-TT",
385 {
386 DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
387 },
388 (void *)NTC1_UARTCLK,
389 },
390 {
391 .ident = "MinnowBoard",
392 {
393 DMI_MATCH(DMI_BOARD_NAME, "MinnowBoard"),
394 },
395 (void *)MINNOW_UARTCLK,
396 },
Wei Yongjunbeadba52016-10-23 11:38:18 +0000397 { }
Darren Hart4e3234892013-07-12 17:58:05 -0700398};
399
Darren Hart077175f2012-03-09 09:51:49 -0800400/* Return UART clock, checking for board specific clocks. */
Darren Harte26439c2013-07-29 15:15:07 -0700401static unsigned int pch_uart_get_uartclk(void)
Darren Hart077175f2012-03-09 09:51:49 -0800402{
Darren Hart4e3234892013-07-12 17:58:05 -0700403 const struct dmi_system_id *d;
Darren Hart077175f2012-03-09 09:51:49 -0800404
Darren Hart2a44feb2012-03-09 09:51:50 -0800405 if (user_uartclk)
406 return user_uartclk;
407
Darren Hart4e3234892013-07-12 17:58:05 -0700408 d = dmi_first_match(pch_uart_dmi_table);
409 if (d)
Darren Harte26439c2013-07-29 15:15:07 -0700410 return (unsigned long)d->driver_data;
Darren Hart29692d02013-06-25 18:53:22 -0700411
Darren Hart077175f2012-03-09 09:51:49 -0800412 return DEFAULT_UARTCLK;
413}
414
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900415static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv,
416 unsigned int flag)
417{
418 u8 ier = ioread8(priv->membase + UART_IER);
419 ier |= flag & PCH_UART_IER_MASK;
420 iowrite8(ier, priv->membase + UART_IER);
421}
422
423static void pch_uart_hal_disable_interrupt(struct eg20t_port *priv,
424 unsigned int flag)
425{
426 u8 ier = ioread8(priv->membase + UART_IER);
427 ier &= ~(flag & PCH_UART_IER_MASK);
428 iowrite8(ier, priv->membase + UART_IER);
429}
430
Darren Harte26439c2013-07-29 15:15:07 -0700431static int pch_uart_hal_set_line(struct eg20t_port *priv, unsigned int baud,
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900432 unsigned int parity, unsigned int bits,
433 unsigned int stb)
434{
435 unsigned int dll, dlm, lcr;
436 int div;
437
Darren Harta8a3ec92012-03-09 09:51:48 -0800438 div = DIV_ROUND_CLOSEST(priv->uartclk / 16, baud);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900439 if (div < 0 || USHRT_MAX <= div) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900440 dev_err(priv->port.dev, "Invalid Baud(div=0x%x)\n", div);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900441 return -EINVAL;
442 }
443
444 dll = (unsigned int)div & 0x00FFU;
445 dlm = ((unsigned int)div >> 8) & 0x00FFU;
446
447 if (parity & ~(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS | PCH_UART_LCR_SP)) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900448 dev_err(priv->port.dev, "Invalid parity(0x%x)\n", parity);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900449 return -EINVAL;
450 }
451
452 if (bits & ~PCH_UART_LCR_WLS) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900453 dev_err(priv->port.dev, "Invalid bits(0x%x)\n", bits);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900454 return -EINVAL;
455 }
456
457 if (stb & ~PCH_UART_LCR_STB) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900458 dev_err(priv->port.dev, "Invalid STB(0x%x)\n", stb);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900459 return -EINVAL;
460 }
461
462 lcr = parity;
463 lcr |= bits;
464 lcr |= stb;
465
Darren Harte26439c2013-07-29 15:15:07 -0700466 dev_dbg(priv->port.dev, "%s:baud = %u, div = %04x, lcr = %02x (%lu)\n",
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900467 __func__, baud, div, lcr, jiffies);
468 iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
469 iowrite8(dll, priv->membase + PCH_UART_DLL);
470 iowrite8(dlm, priv->membase + PCH_UART_DLM);
471 iowrite8(lcr, priv->membase + UART_LCR);
472
473 return 0;
474}
475
476static int pch_uart_hal_fifo_reset(struct eg20t_port *priv,
477 unsigned int flag)
478{
479 if (flag & ~(PCH_UART_FCR_TFR | PCH_UART_FCR_RFR)) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900480 dev_err(priv->port.dev, "%s:Invalid flag(0x%x)\n",
481 __func__, flag);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900482 return -EINVAL;
483 }
484
485 iowrite8(PCH_UART_FCR_FIFOE | priv->fcr, priv->membase + UART_FCR);
486 iowrite8(PCH_UART_FCR_FIFOE | priv->fcr | flag,
487 priv->membase + UART_FCR);
488 iowrite8(priv->fcr, priv->membase + UART_FCR);
489
490 return 0;
491}
492
493static int pch_uart_hal_set_fifo(struct eg20t_port *priv,
494 unsigned int dmamode,
495 unsigned int fifo_size, unsigned int trigger)
496{
497 u8 fcr;
498
499 if (dmamode & ~PCH_UART_FCR_DMS) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900500 dev_err(priv->port.dev, "%s:Invalid DMA Mode(0x%x)\n",
501 __func__, dmamode);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900502 return -EINVAL;
503 }
504
505 if (fifo_size & ~(PCH_UART_FCR_FIFOE | PCH_UART_FCR_FIFO256)) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900506 dev_err(priv->port.dev, "%s:Invalid FIFO SIZE(0x%x)\n",
507 __func__, fifo_size);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900508 return -EINVAL;
509 }
510
511 if (trigger & ~PCH_UART_FCR_RFTL) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900512 dev_err(priv->port.dev, "%s:Invalid TRIGGER(0x%x)\n",
513 __func__, trigger);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900514 return -EINVAL;
515 }
516
517 switch (priv->fifo_size) {
518 case 256:
519 priv->trigger_level =
520 trigger_level_256[trigger >> PCH_UART_FCR_RFTL_SHIFT];
521 break;
522 case 64:
523 priv->trigger_level =
524 trigger_level_64[trigger >> PCH_UART_FCR_RFTL_SHIFT];
525 break;
526 case 16:
527 priv->trigger_level =
528 trigger_level_16[trigger >> PCH_UART_FCR_RFTL_SHIFT];
529 break;
530 default:
531 priv->trigger_level =
532 trigger_level_1[trigger >> PCH_UART_FCR_RFTL_SHIFT];
533 break;
534 }
535 fcr =
536 dmamode | fifo_size | trigger | PCH_UART_FCR_RFR | PCH_UART_FCR_TFR;
537 iowrite8(PCH_UART_FCR_FIFOE, priv->membase + UART_FCR);
538 iowrite8(PCH_UART_FCR_FIFOE | PCH_UART_FCR_RFR | PCH_UART_FCR_TFR,
539 priv->membase + UART_FCR);
540 iowrite8(fcr, priv->membase + UART_FCR);
541 priv->fcr = fcr;
542
543 return 0;
544}
545
546static u8 pch_uart_hal_get_modem(struct eg20t_port *priv)
547{
Feng Tang30c6c6b2012-02-06 17:24:44 +0800548 unsigned int msr = ioread8(priv->membase + UART_MSR);
549 priv->dmsr = msr & PCH_UART_MSR_DELTA;
550 return (u8)msr;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900551}
552
Tomoya MORINAGA18220762011-02-23 10:03:14 +0900553static void pch_uart_hal_write(struct eg20t_port *priv,
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900554 const unsigned char *buf, int tx_size)
555{
556 int i;
557 unsigned int thr;
558
559 for (i = 0; i < tx_size;) {
560 thr = buf[i++];
561 iowrite8(thr, priv->membase + PCH_UART_THR);
562 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900563}
564
565static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
566 int rx_size)
567{
568 int i;
569 u8 rbr, lsr;
Liang Li1f9db092013-01-19 17:52:11 +0800570 struct uart_port *port = &priv->port;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900571
572 lsr = ioread8(priv->membase + UART_LSR);
573 for (i = 0, lsr = ioread8(priv->membase + UART_LSR);
Liang Li1f9db092013-01-19 17:52:11 +0800574 i < rx_size && lsr & (UART_LSR_DR | UART_LSR_BI);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900575 lsr = ioread8(priv->membase + UART_LSR)) {
576 rbr = ioread8(priv->membase + PCH_UART_RBR);
Liang Li1f9db092013-01-19 17:52:11 +0800577
578 if (lsr & UART_LSR_BI) {
579 port->icount.brk++;
580 if (uart_handle_break(port))
581 continue;
582 }
Dmitry Safonoveff0a312019-12-13 00:06:29 +0000583 if (uart_handle_sysrq_char(port, rbr))
584 continue;
Liang Li1f9db092013-01-19 17:52:11 +0800585
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900586 buf[i++] = rbr;
587 }
588 return i;
589}
590
Tomoya MORINAGA2a583642012-03-26 14:43:01 +0900591static unsigned char pch_uart_hal_get_iid(struct eg20t_port *priv)
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900592{
Tomoya MORINAGA2a583642012-03-26 14:43:01 +0900593 return ioread8(priv->membase + UART_IIR) &\
594 (PCH_UART_IIR_IID | PCH_UART_IIR_TOI | PCH_UART_IIR_IP);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900595}
596
597static u8 pch_uart_hal_get_line_status(struct eg20t_port *priv)
598{
599 return ioread8(priv->membase + UART_LSR);
600}
601
602static void pch_uart_hal_set_break(struct eg20t_port *priv, int on)
603{
604 unsigned int lcr;
605
606 lcr = ioread8(priv->membase + UART_LCR);
607 if (on)
608 lcr |= PCH_UART_LCR_SB;
609 else
610 lcr &= ~PCH_UART_LCR_SB;
611
612 iowrite8(lcr, priv->membase + UART_LCR);
613}
614
615static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
616 int size)
617{
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100618 struct uart_port *port = &priv->port;
619 struct tty_port *tport = &port->state->port;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900620
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100621 tty_insert_flip_string(tport, buf, size);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100622 tty_flip_buffer_push(tport);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900623
624 return 0;
625}
626
627static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
628{
Feng Tang30c6c6b2012-02-06 17:24:44 +0800629 int ret = 0;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900630 struct uart_port *port = &priv->port;
631
632 if (port->x_char) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900633 dev_dbg(priv->port.dev, "%s:X character send %02x (%lu)\n",
634 __func__, port->x_char, jiffies);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900635 buf[0] = port->x_char;
636 port->x_char = 0;
637 ret = 1;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900638 }
639
640 return ret;
641}
642
643static int dma_push_rx(struct eg20t_port *priv, int size)
644{
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900645 int room;
646 struct uart_port *port = &priv->port;
Jiri Slaby227434f2013-01-03 15:53:01 +0100647 struct tty_port *tport = &port->state->port;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900648
Jiri Slaby227434f2013-01-03 15:53:01 +0100649 room = tty_buffer_request_room(tport, size);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900650
651 if (room < size)
652 dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
653 size - room);
654 if (!room)
Johan Hovold0b538612013-09-10 12:50:51 +0200655 return 0;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900656
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100657 tty_insert_flip_string(tport, sg_virt(&priv->sg_rx), size);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900658
659 port->icount.rx += room;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900660
661 return room;
662}
663
664static void pch_free_dma(struct uart_port *port)
665{
666 struct eg20t_port *priv;
667 priv = container_of(port, struct eg20t_port, port);
668
669 if (priv->chan_tx) {
670 dma_release_channel(priv->chan_tx);
671 priv->chan_tx = NULL;
672 }
673 if (priv->chan_rx) {
674 dma_release_channel(priv->chan_rx);
675 priv->chan_rx = NULL;
676 }
Tomoya MORINAGAef4f9d42012-03-26 14:43:06 +0900677
678 if (priv->rx_buf_dma) {
679 dma_free_coherent(port->dev, port->fifosize, priv->rx_buf_virt,
680 priv->rx_buf_dma);
681 priv->rx_buf_virt = NULL;
682 priv->rx_buf_dma = 0;
683 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900684
685 return;
686}
687
688static bool filter(struct dma_chan *chan, void *slave)
689{
690 struct pch_dma_slave *param = slave;
691
692 if ((chan->chan_id == param->chan_id) && (param->dma_dev ==
693 chan->device->dev)) {
694 chan->private = param;
695 return true;
696 } else {
697 return false;
698 }
699}
700
701static void pch_request_dma(struct uart_port *port)
702{
703 dma_cap_mask_t mask;
704 struct dma_chan *chan;
705 struct pci_dev *dma_dev;
706 struct pch_dma_slave *param;
707 struct eg20t_port *priv =
708 container_of(port, struct eg20t_port, port);
709 dma_cap_zero(mask);
710 dma_cap_set(DMA_SLAVE, mask);
711
Andy Shevchenko8368d6a2014-07-30 18:59:52 +0300712 /* Get DMA's dev information */
713 dma_dev = pci_get_slot(priv->pdev->bus,
714 PCI_DEVFN(PCI_SLOT(priv->pdev->devfn), 0));
715
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900716 /* Set Tx DMA */
717 param = &priv->param_tx;
718 param->dma_dev = &dma_dev->dev;
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +0900719 param->chan_id = priv->port.line * 2; /* Tx = 0, 2, 4, ... */
720
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900721 param->tx_reg = port->mapbase + UART_TX;
722 chan = dma_request_channel(mask, filter, param);
723 if (!chan) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900724 dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Tx)\n",
725 __func__);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900726 return;
727 }
728 priv->chan_tx = chan;
729
730 /* Set Rx DMA */
731 param = &priv->param_rx;
732 param->dma_dev = &dma_dev->dev;
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +0900733 param->chan_id = priv->port.line * 2 + 1; /* Rx = Tx + 1 */
734
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900735 param->rx_reg = port->mapbase + UART_RX;
736 chan = dma_request_channel(mask, filter, param);
737 if (!chan) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900738 dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",
739 __func__);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900740 dma_release_channel(priv->chan_tx);
Tomoya MORINAGA90f04c22011-11-11 10:55:27 +0900741 priv->chan_tx = NULL;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900742 return;
743 }
744
745 /* Get Consistent memory for DMA */
746 priv->rx_buf_virt = dma_alloc_coherent(port->dev, port->fifosize,
747 &priv->rx_buf_dma, GFP_KERNEL);
748 priv->chan_rx = chan;
749}
750
751static void pch_dma_rx_complete(void *arg)
752{
753 struct eg20t_port *priv = arg;
754 struct uart_port *port = &priv->port;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900755 int count;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900756
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900757 dma_sync_sg_for_cpu(port->dev, &priv->sg_rx, 1, DMA_FROM_DEVICE);
758 count = dma_push_rx(priv, priv->trigger_level);
759 if (count)
Jiri Slaby2e124b42013-01-03 15:53:06 +0100760 tty_flip_buffer_push(&port->state->port);
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900761 async_tx_ack(priv->desc_rx);
Tomoya MORINAGAae213f32012-07-06 17:19:42 +0900762 pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT |
763 PCH_UART_HAL_RX_ERR_INT);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900764}
765
766static void pch_dma_tx_complete(void *arg)
767{
768 struct eg20t_port *priv = arg;
769 struct uart_port *port = &priv->port;
770 struct circ_buf *xmit = &port->state->xmit;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900771 struct scatterlist *sg = priv->sg_tx_p;
772 int i;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900773
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900774 for (i = 0; i < priv->nent; i++, sg++) {
775 xmit->tail += sg_dma_len(sg);
776 port->icount.tx += sg_dma_len(sg);
777 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900778 xmit->tail &= UART_XMIT_SIZE - 1;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900779 async_tx_ack(priv->desc_tx);
Peng Fan74887542019-11-13 05:37:42 +0000780 dma_unmap_sg(port->dev, sg, priv->orig_nent, DMA_TO_DEVICE);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900781 priv->tx_dma_use = 0;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900782 priv->nent = 0;
Peng Fan74887542019-11-13 05:37:42 +0000783 priv->orig_nent = 0;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900784 kfree(priv->sg_tx_p);
Tomoya MORINAGA60d10312011-02-23 10:03:18 +0900785 pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900786}
787
Tomoya MORINAGA18220762011-02-23 10:03:14 +0900788static int pop_tx(struct eg20t_port *priv, int size)
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900789{
790 int count = 0;
791 struct uart_port *port = &priv->port;
792 struct circ_buf *xmit = &port->state->xmit;
793
794 if (uart_tx_stopped(port) || uart_circ_empty(xmit) || count >= size)
795 goto pop_tx_end;
796
797 do {
798 int cnt_to_end =
799 CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
800 int sz = min(size - count, cnt_to_end);
Tomoya MORINAGA18220762011-02-23 10:03:14 +0900801 pch_uart_hal_write(priv, &xmit->buf[xmit->tail], sz);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900802 xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1);
803 count += sz;
804 } while (!uart_circ_empty(xmit) && count < size);
805
806pop_tx_end:
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900807 dev_dbg(priv->port.dev, "%d characters. Remained %d characters.(%lu)\n",
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900808 count, size - count, jiffies);
809
810 return count;
811}
812
813static int handle_rx_to(struct eg20t_port *priv)
814{
815 struct pch_uart_buffer *buf;
816 int rx_size;
817 int ret;
818 if (!priv->start_rx) {
Tomoya MORINAGAae213f32012-07-06 17:19:42 +0900819 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT |
820 PCH_UART_HAL_RX_ERR_INT);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900821 return 0;
822 }
823 buf = &priv->rxbuf;
824 do {
825 rx_size = pch_uart_hal_read(priv, buf->buf, buf->size);
826 ret = push_rx(priv, buf->buf, rx_size);
827 if (ret)
828 return 0;
829 } while (rx_size == buf->size);
830
831 return PCH_UART_HANDLED_RX_INT;
832}
833
834static int handle_rx(struct eg20t_port *priv)
835{
836 return handle_rx_to(priv);
837}
838
839static int dma_handle_rx(struct eg20t_port *priv)
840{
841 struct uart_port *port = &priv->port;
842 struct dma_async_tx_descriptor *desc;
843 struct scatterlist *sg;
844
845 priv = container_of(port, struct eg20t_port, port);
846 sg = &priv->sg_rx;
847
848 sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */
849
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900850 sg_dma_len(sg) = priv->trigger_level;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900851
852 sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt),
Geliang Tangd1e06a42017-04-22 09:21:11 +0800853 sg_dma_len(sg), offset_in_page(priv->rx_buf_virt));
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900854
855 sg_dma_address(sg) = priv->rx_buf_dma;
856
Alexandre Bounine16052822012-03-08 16:11:18 -0500857 desc = dmaengine_prep_slave_sg(priv->chan_rx,
Vinod Koula485df42011-10-14 10:47:38 +0530858 sg, 1, DMA_DEV_TO_MEM,
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900859 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
860
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900861 if (!desc)
862 return 0;
863
864 priv->desc_rx = desc;
865 desc->callback = pch_dma_rx_complete;
866 desc->callback_param = priv;
867 desc->tx_submit(desc);
868 dma_async_issue_pending(priv->chan_rx);
869
870 return PCH_UART_HANDLED_RX_INT;
871}
872
873static unsigned int handle_tx(struct eg20t_port *priv)
874{
875 struct uart_port *port = &priv->port;
876 struct circ_buf *xmit = &port->state->xmit;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900877 int fifo_size;
878 int tx_size;
879 int size;
880 int tx_empty;
881
882 if (!priv->start_tx) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900883 dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
884 __func__, jiffies);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900885 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
886 priv->tx_empty = 1;
887 return 0;
888 }
889
890 fifo_size = max(priv->fifo_size, 1);
891 tx_empty = 1;
892 if (pop_tx_x(priv, xmit->buf)) {
893 pch_uart_hal_write(priv, xmit->buf, 1);
894 port->icount.tx++;
895 tx_empty = 0;
896 fifo_size--;
897 }
898 size = min(xmit->head - xmit->tail, fifo_size);
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900899 if (size < 0)
900 size = fifo_size;
901
Tomoya MORINAGA18220762011-02-23 10:03:14 +0900902 tx_size = pop_tx(priv, size);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900903 if (tx_size > 0) {
Tomoya MORINAGA18220762011-02-23 10:03:14 +0900904 port->icount.tx += tx_size;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900905 tx_empty = 0;
906 }
907
908 priv->tx_empty = tx_empty;
909
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900910 if (tx_empty) {
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900911 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900912 uart_write_wakeup(port);
913 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900914
915 return PCH_UART_HANDLED_TX_INT;
916}
917
918static unsigned int dma_handle_tx(struct eg20t_port *priv)
919{
920 struct uart_port *port = &priv->port;
921 struct circ_buf *xmit = &port->state->xmit;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900922 struct scatterlist *sg;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900923 int nent;
924 int fifo_size;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900925 struct dma_async_tx_descriptor *desc;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900926 int num;
927 int i;
928 int bytes;
929 int size;
930 int rem;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900931
932 if (!priv->start_tx) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900933 dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
934 __func__, jiffies);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900935 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
936 priv->tx_empty = 1;
937 return 0;
938 }
939
Tomoya MORINAGA60d10312011-02-23 10:03:18 +0900940 if (priv->tx_dma_use) {
941 dev_dbg(priv->port.dev, "%s:Tx is not completed. (%lu)\n",
942 __func__, jiffies);
943 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
944 priv->tx_empty = 1;
945 return 0;
946 }
947
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900948 fifo_size = max(priv->fifo_size, 1);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900949 if (pop_tx_x(priv, xmit->buf)) {
950 pch_uart_hal_write(priv, xmit->buf, 1);
951 port->icount.tx++;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900952 fifo_size--;
953 }
954
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900955 bytes = min((int)CIRC_CNT(xmit->head, xmit->tail,
956 UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
957 xmit->tail, UART_XMIT_SIZE));
958 if (!bytes) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900959 dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__);
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900960 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
961 uart_write_wakeup(port);
962 return 0;
963 }
964
965 if (bytes > fifo_size) {
966 num = bytes / fifo_size + 1;
967 size = fifo_size;
968 rem = bytes % fifo_size;
969 } else {
970 num = 1;
971 size = bytes;
972 rem = bytes;
973 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900974
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +0900975 dev_dbg(priv->port.dev, "%s num=%d size=%d rem=%d\n",
976 __func__, num, size, rem);
977
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900978 priv->tx_dma_use = 1;
979
Julia Lawall290ff182020-09-20 13:26:13 +0200980 priv->sg_tx_p = kmalloc_array(num, sizeof(struct scatterlist), GFP_ATOMIC);
Fengguang Wua92098a2012-07-28 20:43:57 +0800981 if (!priv->sg_tx_p) {
982 dev_err(priv->port.dev, "%s:kzalloc Failed\n", __func__);
983 return 0;
984 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900985
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900986 sg_init_table(priv->sg_tx_p, num); /* Initialize SG table */
987 sg = priv->sg_tx_p;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +0900988
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +0900989 for (i = 0; i < num; i++, sg++) {
990 if (i == (num - 1))
991 sg_set_page(sg, virt_to_page(xmit->buf),
992 rem, fifo_size * i);
993 else
994 sg_set_page(sg, virt_to_page(xmit->buf),
995 size, fifo_size * i);
996 }
997
998 sg = priv->sg_tx_p;
999 nent = dma_map_sg(port->dev, sg, num, DMA_TO_DEVICE);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001000 if (!nent) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001001 dev_err(priv->port.dev, "%s:dma_map_sg Failed\n", __func__);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001002 return 0;
1003 }
Peng Fan74887542019-11-13 05:37:42 +00001004 priv->orig_nent = num;
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001005 priv->nent = nent;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001006
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001007 for (i = 0; i < nent; i++, sg++) {
1008 sg->offset = (xmit->tail & (UART_XMIT_SIZE - 1)) +
1009 fifo_size * i;
1010 sg_dma_address(sg) = (sg_dma_address(sg) &
1011 ~(UART_XMIT_SIZE - 1)) + sg->offset;
1012 if (i == (nent - 1))
1013 sg_dma_len(sg) = rem;
1014 else
1015 sg_dma_len(sg) = size;
1016 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001017
Alexandre Bounine16052822012-03-08 16:11:18 -05001018 desc = dmaengine_prep_slave_sg(priv->chan_tx,
Vinod Koula485df42011-10-14 10:47:38 +05301019 priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001020 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001021 if (!desc) {
Geert Uytterhoeven493671a2014-07-11 18:13:26 +02001022 dev_err(priv->port.dev, "%s:dmaengine_prep_slave_sg Failed\n",
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001023 __func__);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001024 return 0;
1025 }
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001026 dma_sync_sg_for_device(port->dev, priv->sg_tx_p, nent, DMA_TO_DEVICE);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001027 priv->desc_tx = desc;
1028 desc->callback = pch_dma_tx_complete;
1029 desc->callback_param = priv;
1030
1031 desc->tx_submit(desc);
1032
1033 dma_async_issue_pending(priv->chan_tx);
1034
1035 return PCH_UART_HANDLED_TX_INT;
1036}
1037
1038static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
1039{
Liang Li384e3012013-01-19 17:52:10 +08001040 struct uart_port *port = &priv->port;
1041 struct tty_struct *tty = tty_port_tty_get(&port->state->port);
1042 char *error_msg[5] = {};
1043 int i = 0;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001044
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001045 if (lsr & PCH_UART_LSR_ERR)
Liang Li384e3012013-01-19 17:52:10 +08001046 error_msg[i++] = "Error data in FIFO\n";
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001047
Liang Li384e3012013-01-19 17:52:10 +08001048 if (lsr & UART_LSR_FE) {
1049 port->icount.frame++;
1050 error_msg[i++] = " Framing Error\n";
1051 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001052
Liang Li384e3012013-01-19 17:52:10 +08001053 if (lsr & UART_LSR_PE) {
1054 port->icount.parity++;
1055 error_msg[i++] = " Parity Error\n";
1056 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001057
Liang Li384e3012013-01-19 17:52:10 +08001058 if (lsr & UART_LSR_OE) {
1059 port->icount.overrun++;
1060 error_msg[i++] = " Overrun Error\n";
1061 }
1062
1063 if (tty == NULL) {
1064 for (i = 0; error_msg[i] != NULL; i++)
1065 dev_err(&priv->pdev->dev, error_msg[i]);
Johan Hovoldfc0919c2013-09-10 12:50:49 +02001066 } else {
1067 tty_kref_put(tty);
Liang Li384e3012013-01-19 17:52:10 +08001068 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001069}
1070
1071static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
1072{
1073 struct eg20t_port *priv = dev_id;
1074 unsigned int handled;
1075 u8 lsr;
1076 int ret = 0;
Tomoya MORINAGA2a583642012-03-26 14:43:01 +09001077 unsigned char iid;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001078 unsigned long flags;
Tomoya MORINAGA5181fb32012-03-26 14:43:03 +09001079 int next = 1;
1080 u8 msr;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001081
Darren Hartfe89def2012-06-19 14:00:18 -07001082 spin_lock_irqsave(&priv->lock, flags);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001083 handled = 0;
Tomoya MORINAGA5181fb32012-03-26 14:43:03 +09001084 while (next) {
1085 iid = pch_uart_hal_get_iid(priv);
1086 if (iid & PCH_UART_IIR_IP) /* No Interrupt */
1087 break;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001088 switch (iid) {
1089 case PCH_UART_IID_RLS: /* Receiver Line Status */
1090 lsr = pch_uart_hal_get_line_status(priv);
1091 if (lsr & (PCH_UART_LSR_ERR | UART_LSR_FE |
1092 UART_LSR_PE | UART_LSR_OE)) {
1093 pch_uart_err_ir(priv, lsr);
1094 ret = PCH_UART_HANDLED_RX_ERR_INT;
Tomoya MORINAGA04e2c2e2012-03-26 14:43:05 +09001095 } else {
1096 ret = PCH_UART_HANDLED_LS_INT;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001097 }
1098 break;
1099 case PCH_UART_IID_RDR: /* Received Data Ready */
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001100 if (priv->use_dma) {
1101 pch_uart_hal_disable_interrupt(priv,
Tomoya MORINAGAae213f32012-07-06 17:19:42 +09001102 PCH_UART_HAL_RX_INT |
1103 PCH_UART_HAL_RX_ERR_INT);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001104 ret = dma_handle_rx(priv);
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001105 if (!ret)
1106 pch_uart_hal_enable_interrupt(priv,
Tomoya MORINAGAae213f32012-07-06 17:19:42 +09001107 PCH_UART_HAL_RX_INT |
1108 PCH_UART_HAL_RX_ERR_INT);
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001109 } else {
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001110 ret = handle_rx(priv);
Tomoya MORINAGAda3564e2011-02-23 10:03:12 +09001111 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001112 break;
1113 case PCH_UART_IID_RDR_TO: /* Received Data Ready
1114 (FIFO Timeout) */
1115 ret = handle_rx_to(priv);
1116 break;
1117 case PCH_UART_IID_THRE: /* Transmitter Holding Register
1118 Empty */
1119 if (priv->use_dma)
1120 ret = dma_handle_tx(priv);
1121 else
1122 ret = handle_tx(priv);
1123 break;
1124 case PCH_UART_IID_MS: /* Modem Status */
Tomoya MORINAGA5181fb32012-03-26 14:43:03 +09001125 msr = pch_uart_hal_get_modem(priv);
1126 next = 0; /* MS ir prioirty is the lowest. So, MS ir
1127 means final interrupt */
1128 if ((msr & UART_MSR_ANY_DELTA) == 0)
1129 break;
1130 ret |= PCH_UART_HANDLED_MS_INT;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001131 break;
1132 default: /* Never junp to this label */
Tomoya MORINAGAb23954a32012-03-26 14:43:02 +09001133 dev_err(priv->port.dev, "%s:iid=%02x (%lu)\n", __func__,
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001134 iid, jiffies);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001135 ret = -1;
Tomoya MORINAGA5181fb32012-03-26 14:43:03 +09001136 next = 0;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001137 break;
1138 }
1139 handled |= (unsigned int)ret;
1140 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001141
Darren Hartfe89def2012-06-19 14:00:18 -07001142 spin_unlock_irqrestore(&priv->lock, flags);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001143 return IRQ_RETVAL(handled);
1144}
1145
1146/* This function tests whether the transmitter fifo and shifter for the port
1147 described by 'port' is empty. */
1148static unsigned int pch_uart_tx_empty(struct uart_port *port)
1149{
1150 struct eg20t_port *priv;
Feng Tang30c6c6b2012-02-06 17:24:44 +08001151
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001152 priv = container_of(port, struct eg20t_port, port);
1153 if (priv->tx_empty)
Feng Tang30c6c6b2012-02-06 17:24:44 +08001154 return TIOCSER_TEMT;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001155 else
Feng Tang30c6c6b2012-02-06 17:24:44 +08001156 return 0;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001157}
1158
1159/* Returns the current state of modem control inputs. */
1160static unsigned int pch_uart_get_mctrl(struct uart_port *port)
1161{
1162 struct eg20t_port *priv;
1163 u8 modem;
1164 unsigned int ret = 0;
1165
1166 priv = container_of(port, struct eg20t_port, port);
1167 modem = pch_uart_hal_get_modem(priv);
1168
1169 if (modem & UART_MSR_DCD)
1170 ret |= TIOCM_CAR;
1171
1172 if (modem & UART_MSR_RI)
1173 ret |= TIOCM_RNG;
1174
1175 if (modem & UART_MSR_DSR)
1176 ret |= TIOCM_DSR;
1177
1178 if (modem & UART_MSR_CTS)
1179 ret |= TIOCM_CTS;
1180
1181 return ret;
1182}
1183
1184static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
1185{
1186 u32 mcr = 0;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001187 struct eg20t_port *priv = container_of(port, struct eg20t_port, port);
1188
1189 if (mctrl & TIOCM_DTR)
1190 mcr |= UART_MCR_DTR;
1191 if (mctrl & TIOCM_RTS)
1192 mcr |= UART_MCR_RTS;
1193 if (mctrl & TIOCM_LOOP)
1194 mcr |= UART_MCR_LOOP;
1195
Tomoya MORINAGA9af71552011-02-23 10:03:17 +09001196 if (priv->mcr & UART_MCR_AFE)
1197 mcr |= UART_MCR_AFE;
1198
1199 if (mctrl)
1200 iowrite8(mcr, priv->membase + UART_MCR);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001201}
1202
1203static void pch_uart_stop_tx(struct uart_port *port)
1204{
1205 struct eg20t_port *priv;
1206 priv = container_of(port, struct eg20t_port, port);
1207 priv->start_tx = 0;
1208 priv->tx_dma_use = 0;
1209}
1210
1211static void pch_uart_start_tx(struct uart_port *port)
1212{
1213 struct eg20t_port *priv;
1214
1215 priv = container_of(port, struct eg20t_port, port);
1216
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001217 if (priv->use_dma) {
1218 if (priv->tx_dma_use) {
1219 dev_dbg(priv->port.dev, "%s : Tx DMA is NOT empty.\n",
1220 __func__);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001221 return;
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001222 }
1223 }
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001224
1225 priv->start_tx = 1;
1226 pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
1227}
1228
1229static void pch_uart_stop_rx(struct uart_port *port)
1230{
1231 struct eg20t_port *priv;
1232 priv = container_of(port, struct eg20t_port, port);
1233 priv->start_rx = 0;
Tomoya MORINAGAae213f32012-07-06 17:19:42 +09001234 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT |
1235 PCH_UART_HAL_RX_ERR_INT);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001236}
1237
1238/* Enable the modem status interrupts. */
1239static void pch_uart_enable_ms(struct uart_port *port)
1240{
1241 struct eg20t_port *priv;
1242 priv = container_of(port, struct eg20t_port, port);
1243 pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_MS_INT);
1244}
1245
1246/* Control the transmission of a break signal. */
1247static void pch_uart_break_ctl(struct uart_port *port, int ctl)
1248{
1249 struct eg20t_port *priv;
1250 unsigned long flags;
1251
1252 priv = container_of(port, struct eg20t_port, port);
Darren Hartfe89def2012-06-19 14:00:18 -07001253 spin_lock_irqsave(&priv->lock, flags);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001254 pch_uart_hal_set_break(priv, ctl);
Darren Hartfe89def2012-06-19 14:00:18 -07001255 spin_unlock_irqrestore(&priv->lock, flags);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001256}
1257
1258/* Grab any interrupt resources and initialise any low level driver state. */
1259static int pch_uart_startup(struct uart_port *port)
1260{
1261 struct eg20t_port *priv;
1262 int ret;
1263 int fifo_size;
1264 int trigger_level;
1265
1266 priv = container_of(port, struct eg20t_port, port);
1267 priv->tx_empty = 1;
Tomoya MORINAGAaac6c0b2011-02-23 10:03:16 +09001268
1269 if (port->uartclk)
Darren Harta8a3ec92012-03-09 09:51:48 -08001270 priv->uartclk = port->uartclk;
Tomoya MORINAGAaac6c0b2011-02-23 10:03:16 +09001271 else
Darren Harta8a3ec92012-03-09 09:51:48 -08001272 port->uartclk = priv->uartclk;
Tomoya MORINAGAaac6c0b2011-02-23 10:03:16 +09001273
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001274 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
1275 ret = pch_uart_hal_set_line(priv, default_baud,
1276 PCH_UART_HAL_PARITY_NONE, PCH_UART_HAL_8BIT,
1277 PCH_UART_HAL_STB1);
1278 if (ret)
1279 return ret;
1280
1281 switch (priv->fifo_size) {
1282 case 256:
1283 fifo_size = PCH_UART_HAL_FIFO256;
1284 break;
1285 case 64:
1286 fifo_size = PCH_UART_HAL_FIFO64;
1287 break;
1288 case 16:
1289 fifo_size = PCH_UART_HAL_FIFO16;
Alan Cox669bd452012-07-02 18:51:38 +01001290 break;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001291 case 1:
1292 default:
1293 fifo_size = PCH_UART_HAL_FIFO_DIS;
1294 break;
1295 }
1296
1297 switch (priv->trigger) {
1298 case PCH_UART_HAL_TRIGGER1:
1299 trigger_level = 1;
1300 break;
1301 case PCH_UART_HAL_TRIGGER_L:
1302 trigger_level = priv->fifo_size / 4;
1303 break;
1304 case PCH_UART_HAL_TRIGGER_M:
1305 trigger_level = priv->fifo_size / 2;
1306 break;
1307 case PCH_UART_HAL_TRIGGER_H:
1308 default:
1309 trigger_level = priv->fifo_size - (priv->fifo_size / 8);
1310 break;
1311 }
1312
1313 priv->trigger_level = trigger_level;
1314 ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0,
1315 fifo_size, priv->trigger);
1316 if (ret < 0)
1317 return ret;
1318
1319 ret = request_irq(priv->port.irq, pch_uart_interrupt, IRQF_SHARED,
Alexander Stein50d16ca2014-03-25 14:05:08 +01001320 priv->irq_name, priv);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001321 if (ret < 0)
1322 return ret;
1323
1324 if (priv->use_dma)
1325 pch_request_dma(port);
1326
1327 priv->start_rx = 1;
Tomoya MORINAGAae213f32012-07-06 17:19:42 +09001328 pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT |
1329 PCH_UART_HAL_RX_ERR_INT);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001330 uart_update_timeout(port, CS8, default_baud);
1331
1332 return 0;
1333}
1334
1335static void pch_uart_shutdown(struct uart_port *port)
1336{
1337 struct eg20t_port *priv;
1338 int ret;
1339
1340 priv = container_of(port, struct eg20t_port, port);
1341 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
1342 pch_uart_hal_fifo_reset(priv, PCH_UART_HAL_CLR_ALL_FIFO);
1343 ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0,
1344 PCH_UART_HAL_FIFO_DIS, PCH_UART_HAL_TRIGGER1);
1345 if (ret)
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001346 dev_err(priv->port.dev,
1347 "pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001348
Tomoya MORINAGA90f04c22011-11-11 10:55:27 +09001349 pch_free_dma(port);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001350
1351 free_irq(priv->port.irq, priv);
1352}
1353
1354/* Change the port parameters, including word length, parity, stop
1355 *bits. Update read_status_mask and ignore_status_mask to indicate
1356 *the types of events we are interested in receiving. */
1357static void pch_uart_set_termios(struct uart_port *port,
1358 struct ktermios *termios, struct ktermios *old)
1359{
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001360 int rtn;
Darren Harte26439c2013-07-29 15:15:07 -07001361 unsigned int baud, parity, bits, stb;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001362 struct eg20t_port *priv;
1363 unsigned long flags;
1364
1365 priv = container_of(port, struct eg20t_port, port);
1366 switch (termios->c_cflag & CSIZE) {
1367 case CS5:
1368 bits = PCH_UART_HAL_5BIT;
1369 break;
1370 case CS6:
1371 bits = PCH_UART_HAL_6BIT;
1372 break;
1373 case CS7:
1374 bits = PCH_UART_HAL_7BIT;
1375 break;
1376 default: /* CS8 */
1377 bits = PCH_UART_HAL_8BIT;
1378 break;
1379 }
1380 if (termios->c_cflag & CSTOPB)
1381 stb = PCH_UART_HAL_STB2;
1382 else
1383 stb = PCH_UART_HAL_STB1;
1384
1385 if (termios->c_cflag & PARENB) {
Tomoya MORINAGA2fc39ae2012-07-06 17:19:43 +09001386 if (termios->c_cflag & PARODD)
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001387 parity = PCH_UART_HAL_PARITY_ODD;
1388 else
1389 parity = PCH_UART_HAL_PARITY_EVEN;
1390
Feng Tang30c6c6b2012-02-06 17:24:44 +08001391 } else
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001392 parity = PCH_UART_HAL_PARITY_NONE;
Tomoya MORINAGA9af71552011-02-23 10:03:17 +09001393
1394 /* Only UART0 has auto hardware flow function */
1395 if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256))
1396 priv->mcr |= UART_MCR_AFE;
1397 else
1398 priv->mcr &= ~UART_MCR_AFE;
1399
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001400 termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
1401
1402 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
1403
Darren Hartfe89def2012-06-19 14:00:18 -07001404 spin_lock_irqsave(&priv->lock, flags);
1405 spin_lock(&port->lock);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001406
1407 uart_update_timeout(port, termios->c_cflag, baud);
1408 rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb);
1409 if (rtn)
1410 goto out;
1411
Tomoya MORINAGAa1d7cfe2011-10-27 15:45:18 +09001412 pch_uart_set_mctrl(&priv->port, priv->port.mctrl);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001413 /* Don't rewrite B0 */
1414 if (tty_termios_baud_rate(termios))
1415 tty_termios_encode_baud_rate(termios, baud, baud);
1416
1417out:
Darren Hartfe89def2012-06-19 14:00:18 -07001418 spin_unlock(&port->lock);
1419 spin_unlock_irqrestore(&priv->lock, flags);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001420}
1421
1422static const char *pch_uart_type(struct uart_port *port)
1423{
1424 return KBUILD_MODNAME;
1425}
1426
1427static void pch_uart_release_port(struct uart_port *port)
1428{
1429 struct eg20t_port *priv;
1430
1431 priv = container_of(port, struct eg20t_port, port);
1432 pci_iounmap(priv->pdev, priv->membase);
1433 pci_release_regions(priv->pdev);
1434}
1435
1436static int pch_uart_request_port(struct uart_port *port)
1437{
1438 struct eg20t_port *priv;
1439 int ret;
1440 void __iomem *membase;
1441
1442 priv = container_of(port, struct eg20t_port, port);
1443 ret = pci_request_regions(priv->pdev, KBUILD_MODNAME);
1444 if (ret < 0)
1445 return -EBUSY;
1446
1447 membase = pci_iomap(priv->pdev, 1, 0);
1448 if (!membase) {
1449 pci_release_regions(priv->pdev);
1450 return -EBUSY;
1451 }
1452 priv->membase = port->membase = membase;
1453
1454 return 0;
1455}
1456
1457static void pch_uart_config_port(struct uart_port *port, int type)
1458{
1459 struct eg20t_port *priv;
1460
1461 priv = container_of(port, struct eg20t_port, port);
1462 if (type & UART_CONFIG_TYPE) {
1463 port->type = priv->port_type;
1464 pch_uart_request_port(port);
1465 }
1466}
1467
1468static int pch_uart_verify_port(struct uart_port *port,
1469 struct serial_struct *serinfo)
1470{
1471 struct eg20t_port *priv;
1472
1473 priv = container_of(port, struct eg20t_port, port);
1474 if (serinfo->flags & UPF_LOW_LATENCY) {
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001475 dev_info(priv->port.dev,
1476 "PCH UART : Use PIO Mode (without DMA)\n");
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001477 priv->use_dma = 0;
1478 serinfo->flags &= ~UPF_LOW_LATENCY;
1479 } else {
1480#ifndef CONFIG_PCH_DMA
Tomoya MORINAGA23877fd2011-02-23 10:03:15 +09001481 dev_err(priv->port.dev, "%s : PCH DMA is not Loaded.\n",
1482 __func__);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001483 return -EOPNOTSUPP;
1484#endif
Sebastian Andrzej Siewiore41c0982013-12-04 20:52:49 +01001485 if (!priv->use_dma) {
Tomoya MORINAGAaf6d17c2012-04-12 10:47:50 +09001486 pch_request_dma(port);
Sebastian Andrzej Siewiore41c0982013-12-04 20:52:49 +01001487 if (priv->chan_rx)
1488 priv->use_dma = 1;
1489 }
1490 dev_info(priv->port.dev, "PCH UART: %s\n",
1491 priv->use_dma ?
1492 "Use DMA Mode" : "No DMA");
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001493 }
1494
1495 return 0;
1496}
1497
Luis Henriques09a51632013-08-14 23:18:37 +01001498#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_PCH_UART_CONSOLE)
Alexander Steine30f8672011-11-15 15:04:07 -08001499/*
1500 * Wait for transmitter & holding register to empty
1501 */
1502static void wait_for_xmitr(struct eg20t_port *up, int bits)
1503{
1504 unsigned int status, tmout = 10000;
1505
1506 /* Wait up to 10ms for the character(s) to be sent. */
1507 for (;;) {
1508 status = ioread8(up->membase + UART_LSR);
1509
1510 if ((status & bits) == bits)
1511 break;
1512 if (--tmout == 0)
1513 break;
1514 udelay(1);
1515 }
1516
1517 /* Wait up to 1s for flow control if necessary */
1518 if (up->port.flags & UPF_CONS_FLOW) {
1519 unsigned int tmout;
1520 for (tmout = 1000000; tmout; tmout--) {
1521 unsigned int msr = ioread8(up->membase + UART_MSR);
1522 if (msr & UART_MSR_CTS)
1523 break;
1524 udelay(1);
1525 touch_nmi_watchdog();
1526 }
1527 }
1528}
Luis Henriques09a51632013-08-14 23:18:37 +01001529#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_PCH_UART_CONSOLE */
Alexander Steine30f8672011-11-15 15:04:07 -08001530
Liang Lief44d282013-03-05 22:30:38 +08001531#ifdef CONFIG_CONSOLE_POLL
1532/*
1533 * Console polling routines for communicate via uart while
1534 * in an interrupt or debug context.
1535 */
1536static int pch_uart_get_poll_char(struct uart_port *port)
1537{
1538 struct eg20t_port *priv =
1539 container_of(port, struct eg20t_port, port);
1540 u8 lsr = ioread8(priv->membase + UART_LSR);
1541
1542 if (!(lsr & UART_LSR_DR))
1543 return NO_POLL_CHAR;
1544
1545 return ioread8(priv->membase + PCH_UART_RBR);
1546}
1547
1548
1549static void pch_uart_put_poll_char(struct uart_port *port,
1550 unsigned char c)
1551{
1552 unsigned int ier;
1553 struct eg20t_port *priv =
1554 container_of(port, struct eg20t_port, port);
1555
1556 /*
1557 * First save the IER then disable the interrupts
1558 */
1559 ier = ioread8(priv->membase + UART_IER);
1560 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
1561
1562 wait_for_xmitr(priv, UART_LSR_THRE);
1563 /*
1564 * Send the character out.
Liang Lief44d282013-03-05 22:30:38 +08001565 */
1566 iowrite8(c, priv->membase + PCH_UART_THR);
Liang Lief44d282013-03-05 22:30:38 +08001567
1568 /*
1569 * Finally, wait for transmitter to become empty
1570 * and restore the IER
1571 */
1572 wait_for_xmitr(priv, BOTH_EMPTY);
1573 iowrite8(ier, priv->membase + UART_IER);
1574}
1575#endif /* CONFIG_CONSOLE_POLL */
1576
Julia Lawall069a47e2016-09-01 19:51:35 +02001577static const struct uart_ops pch_uart_ops = {
Liang Lief44d282013-03-05 22:30:38 +08001578 .tx_empty = pch_uart_tx_empty,
1579 .set_mctrl = pch_uart_set_mctrl,
1580 .get_mctrl = pch_uart_get_mctrl,
1581 .stop_tx = pch_uart_stop_tx,
1582 .start_tx = pch_uart_start_tx,
1583 .stop_rx = pch_uart_stop_rx,
1584 .enable_ms = pch_uart_enable_ms,
1585 .break_ctl = pch_uart_break_ctl,
1586 .startup = pch_uart_startup,
1587 .shutdown = pch_uart_shutdown,
1588 .set_termios = pch_uart_set_termios,
1589/* .pm = pch_uart_pm, Not supported yet */
Liang Lief44d282013-03-05 22:30:38 +08001590 .type = pch_uart_type,
1591 .release_port = pch_uart_release_port,
1592 .request_port = pch_uart_request_port,
1593 .config_port = pch_uart_config_port,
1594 .verify_port = pch_uart_verify_port,
1595#ifdef CONFIG_CONSOLE_POLL
1596 .poll_get_char = pch_uart_get_poll_char,
1597 .poll_put_char = pch_uart_put_poll_char,
1598#endif
1599};
1600
1601#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
1602
Alexander Steine30f8672011-11-15 15:04:07 -08001603static void pch_console_putchar(struct uart_port *port, int ch)
1604{
1605 struct eg20t_port *priv =
1606 container_of(port, struct eg20t_port, port);
1607
1608 wait_for_xmitr(priv, UART_LSR_THRE);
1609 iowrite8(ch, priv->membase + PCH_UART_THR);
1610}
1611
1612/*
1613 * Print a string to the serial port trying not to disturb
1614 * any possible real use of the port...
1615 *
1616 * The console_lock must be held when we get here.
1617 */
1618static void
1619pch_console_write(struct console *co, const char *s, unsigned int count)
1620{
1621 struct eg20t_port *priv;
Alexander Steine30f8672011-11-15 15:04:07 -08001622 unsigned long flags;
Darren Hartfe89def2012-06-19 14:00:18 -07001623 int priv_locked = 1;
1624 int port_locked = 1;
Alexander Steine30f8672011-11-15 15:04:07 -08001625 u8 ier;
Alexander Steine30f8672011-11-15 15:04:07 -08001626
1627 priv = pch_uart_ports[co->index];
1628
1629 touch_nmi_watchdog();
1630
1631 local_irq_save(flags);
1632 if (priv->port.sysrq) {
Liang Li1f9db092013-01-19 17:52:11 +08001633 /* call to uart_handle_sysrq_char already took the priv lock */
1634 priv_locked = 0;
Darren Hartfe89def2012-06-19 14:00:18 -07001635 /* serial8250_handle_port() already took the port lock */
1636 port_locked = 0;
Alexander Steine30f8672011-11-15 15:04:07 -08001637 } else if (oops_in_progress) {
Darren Hartfe89def2012-06-19 14:00:18 -07001638 priv_locked = spin_trylock(&priv->lock);
1639 port_locked = spin_trylock(&priv->port.lock);
1640 } else {
1641 spin_lock(&priv->lock);
Alexander Steine30f8672011-11-15 15:04:07 -08001642 spin_lock(&priv->port.lock);
Darren Hartfe89def2012-06-19 14:00:18 -07001643 }
Alexander Steine30f8672011-11-15 15:04:07 -08001644
1645 /*
1646 * First save the IER then disable the interrupts
1647 */
1648 ier = ioread8(priv->membase + UART_IER);
1649
1650 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
1651
1652 uart_console_write(&priv->port, s, count, pch_console_putchar);
1653
1654 /*
1655 * Finally, wait for transmitter to become empty
1656 * and restore the IER
1657 */
1658 wait_for_xmitr(priv, BOTH_EMPTY);
1659 iowrite8(ier, priv->membase + UART_IER);
1660
Darren Hartfe89def2012-06-19 14:00:18 -07001661 if (port_locked)
Alexander Steine30f8672011-11-15 15:04:07 -08001662 spin_unlock(&priv->port.lock);
Darren Hartfe89def2012-06-19 14:00:18 -07001663 if (priv_locked)
1664 spin_unlock(&priv->lock);
Alexander Steine30f8672011-11-15 15:04:07 -08001665 local_irq_restore(flags);
1666}
1667
1668static int __init pch_console_setup(struct console *co, char *options)
1669{
1670 struct uart_port *port;
Darren Hart7ce92512012-03-09 09:51:51 -08001671 int baud = default_baud;
Alexander Steine30f8672011-11-15 15:04:07 -08001672 int bits = 8;
1673 int parity = 'n';
1674 int flow = 'n';
1675
1676 /*
1677 * Check whether an invalid uart number has been specified, and
1678 * if so, search for the first available port that does have
1679 * console support.
1680 */
1681 if (co->index >= PCH_UART_NR)
1682 co->index = 0;
1683 port = &pch_uart_ports[co->index]->port;
1684
1685 if (!port || (!port->iobase && !port->membase))
1686 return -ENODEV;
1687
Darren Hart077175f2012-03-09 09:51:49 -08001688 port->uartclk = pch_uart_get_uartclk();
Alexander Steine30f8672011-11-15 15:04:07 -08001689
1690 if (options)
1691 uart_parse_options(options, &baud, &parity, &bits, &flow);
1692
1693 return uart_set_options(port, co, baud, parity, bits, flow);
1694}
1695
1696static struct uart_driver pch_uart_driver;
1697
1698static struct console pch_console = {
1699 .name = PCH_UART_DRIVER_DEVICE,
1700 .write = pch_console_write,
1701 .device = uart_console_device,
1702 .setup = pch_console_setup,
1703 .flags = CON_PRINTBUFFER | CON_ANYTIME,
1704 .index = -1,
1705 .data = &pch_uart_driver,
1706};
1707
1708#define PCH_CONSOLE (&pch_console)
1709#else
1710#define PCH_CONSOLE NULL
Liang Lief44d282013-03-05 22:30:38 +08001711#endif /* CONFIG_SERIAL_PCH_UART_CONSOLE */
Alexander Steine30f8672011-11-15 15:04:07 -08001712
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001713static struct uart_driver pch_uart_driver = {
1714 .owner = THIS_MODULE,
1715 .driver_name = KBUILD_MODNAME,
1716 .dev_name = PCH_UART_DRIVER_DEVICE,
1717 .major = 0,
1718 .minor = 0,
1719 .nr = PCH_UART_NR,
Alexander Steine30f8672011-11-15 15:04:07 -08001720 .cons = PCH_CONSOLE,
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001721};
1722
1723static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001724 const struct pci_device_id *id)
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001725{
1726 struct eg20t_port *priv;
1727 int ret;
1728 unsigned int iobase;
1729 unsigned int mapbase;
Tomoya MORINAGA1c518992010-12-16 16:13:29 +09001730 unsigned char *rxbuf;
Darren Hart077175f2012-03-09 09:51:49 -08001731 int fifosize;
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001732 int port_type;
1733 struct pch_uart_driver_data *board;
Greg Kroah-Hartman4dec5f12021-02-16 15:59:00 +01001734 char name[32];
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001735
1736 board = &drv_dat[id->driver_data];
1737 port_type = board->port_type;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001738
1739 priv = kzalloc(sizeof(struct eg20t_port), GFP_KERNEL);
1740 if (priv == NULL)
1741 goto init_port_alloc_err;
1742
Tomoya MORINAGA1c518992010-12-16 16:13:29 +09001743 rxbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001744 if (!rxbuf)
1745 goto init_port_free_txbuf;
1746
1747 switch (port_type) {
Andy Shevchenko63e8d432017-08-22 16:58:20 +03001748 case PORT_PCH_8LINE:
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001749 fifosize = 256; /* EG20T/ML7213: UART0 */
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001750 break;
Andy Shevchenko63e8d432017-08-22 16:58:20 +03001751 case PORT_PCH_2LINE:
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001752 fifosize = 64; /* EG20T:UART1~3 ML7213: UART1~2*/
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001753 break;
1754 default:
1755 dev_err(&pdev->dev, "Invalid Port Type(=%d)\n", port_type);
1756 goto init_port_hal_free;
1757 }
1758
Alexander Steine4635952011-07-04 08:58:31 +02001759 pci_enable_msi(pdev);
Tomoya MORINAGA867c9022012-04-02 14:36:22 +09001760 pci_set_master(pdev);
Alexander Steine4635952011-07-04 08:58:31 +02001761
Darren Hartfe89def2012-06-19 14:00:18 -07001762 spin_lock_init(&priv->lock);
1763
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001764 iobase = pci_resource_start(pdev, 0);
1765 mapbase = pci_resource_start(pdev, 1);
1766 priv->mapbase = mapbase;
1767 priv->iobase = iobase;
1768 priv->pdev = pdev;
1769 priv->tx_empty = 1;
Tomoya MORINAGA1c518992010-12-16 16:13:29 +09001770 priv->rxbuf.buf = rxbuf;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001771 priv->rxbuf.size = PAGE_SIZE;
1772
1773 priv->fifo_size = fifosize;
Darren Hart077175f2012-03-09 09:51:49 -08001774 priv->uartclk = pch_uart_get_uartclk();
Andy Shevchenko63e8d432017-08-22 16:58:20 +03001775 priv->port_type = port_type;
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001776 priv->port.dev = &pdev->dev;
1777 priv->port.iobase = iobase;
1778 priv->port.membase = NULL;
1779 priv->port.mapbase = mapbase;
1780 priv->port.irq = pdev->irq;
1781 priv->port.iotype = UPIO_PORT;
1782 priv->port.ops = &pch_uart_ops;
1783 priv->port.flags = UPF_BOOT_AUTOCONF;
1784 priv->port.fifosize = fifosize;
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001785 priv->port.line = board->line_no;
Dmitry Safonovbb3ecd92019-12-13 00:06:28 +00001786 priv->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_PCH_UART_CONSOLE);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001787 priv->trigger = PCH_UART_HAL_TRIGGER_M;
1788
Alexander Stein50d16ca2014-03-25 14:05:08 +01001789 snprintf(priv->irq_name, IRQ_NAME_SIZE,
1790 KBUILD_MODNAME ":" PCH_UART_DRIVER_DEVICE "%d",
1791 priv->port.line);
1792
Tomoya MORINAGA7e461322011-02-23 10:03:13 +09001793 spin_lock_init(&priv->port.lock);
1794
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001795 pci_set_drvdata(pdev, priv);
Feng Tang6f56d0f2012-02-06 17:24:45 +08001796 priv->trigger_level = 1;
1797 priv->fcr = 0;
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001798
Zubair Lutfullah Kakakhel7789e5a2016-08-12 12:48:54 +01001799 if (pdev->dev.of_node)
1800 of_property_read_u32(pdev->dev.of_node, "clock-frequency"
1801 , &user_uartclk);
1802
Alexander Steine30f8672011-11-15 15:04:07 -08001803#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
1804 pch_uart_ports[board->line_no] = priv;
1805#endif
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001806 ret = uart_add_one_port(&pch_uart_driver, &priv->port);
1807 if (ret < 0)
1808 goto init_port_hal_free;
1809
Greg Kroah-Hartman4dec5f12021-02-16 15:59:00 +01001810 snprintf(name, sizeof(name), "uart%d_regs", priv->port.line);
1811 debugfs_create_file(name, S_IFREG | S_IRUGO, NULL, priv,
1812 &port_regs_ops);
Feng Tangd0114112012-02-06 17:24:43 +08001813
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001814 return priv;
1815
1816init_port_hal_free:
Alexander Steine30f8672011-11-15 15:04:07 -08001817#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
1818 pch_uart_ports[board->line_no] = NULL;
1819#endif
Tomoya MORINAGA1c518992010-12-16 16:13:29 +09001820 free_page((unsigned long)rxbuf);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001821init_port_free_txbuf:
1822 kfree(priv);
1823init_port_alloc_err:
1824
1825 return NULL;
1826}
1827
1828static void pch_uart_exit_port(struct eg20t_port *priv)
1829{
Greg Kroah-Hartman4dec5f12021-02-16 15:59:00 +01001830 char name[32];
Feng Tangd0114112012-02-06 17:24:43 +08001831
Greg Kroah-Hartman4dec5f12021-02-16 15:59:00 +01001832 snprintf(name, sizeof(name), "uart%d_regs", priv->port.line);
1833 debugfs_remove(debugfs_lookup(name, NULL));
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001834 uart_remove_one_port(&pch_uart_driver, &priv->port);
Tomoya MORINAGA1c518992010-12-16 16:13:29 +09001835 free_page((unsigned long)priv->rxbuf.buf);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001836}
1837
1838static void pch_uart_pci_remove(struct pci_dev *pdev)
1839{
Feng Tang6f56d0f2012-02-06 17:24:45 +08001840 struct eg20t_port *priv = pci_get_drvdata(pdev);
Alexander Steine4635952011-07-04 08:58:31 +02001841
1842 pci_disable_msi(pdev);
Alexander Steine30f8672011-11-15 15:04:07 -08001843
1844#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
1845 pch_uart_ports[priv->port.line] = NULL;
1846#endif
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001847 pch_uart_exit_port(priv);
1848 pci_disable_device(pdev);
1849 kfree(priv);
1850 return;
1851}
Vaibhav Gupta23a98b6e2020-07-20 17:34:15 +05301852
1853static int __maybe_unused pch_uart_pci_suspend(struct device *dev)
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001854{
Vaibhav Gupta23a98b6e2020-07-20 17:34:15 +05301855 struct eg20t_port *priv = dev_get_drvdata(dev);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001856
1857 uart_suspend_port(&pch_uart_driver, &priv->port);
1858
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001859 return 0;
1860}
1861
Vaibhav Gupta23a98b6e2020-07-20 17:34:15 +05301862static int __maybe_unused pch_uart_pci_resume(struct device *dev)
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001863{
Vaibhav Gupta23a98b6e2020-07-20 17:34:15 +05301864 struct eg20t_port *priv = dev_get_drvdata(dev);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001865
1866 uart_resume_port(&pch_uart_driver, &priv->port);
1867
1868 return 0;
1869}
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001870
Jingoo Han311df742013-12-03 08:26:37 +09001871static const struct pci_device_id pch_uart_pci_id[] = {
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001872 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001873 .driver_data = pch_et20t_uart0},
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001874 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812),
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001875 .driver_data = pch_et20t_uart1},
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001876 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8813),
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001877 .driver_data = pch_et20t_uart2},
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001878 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8814),
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001879 .driver_data = pch_et20t_uart3},
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001880 {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8027),
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001881 .driver_data = pch_ml7213_uart0},
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001882 {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8028),
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001883 .driver_data = pch_ml7213_uart1},
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001884 {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029),
Tomoya MORINAGAfec38d12011-02-23 10:03:19 +09001885 .driver_data = pch_ml7213_uart2},
Tomoya MORINAGA177c2cb2011-05-09 17:25:20 +09001886 {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800C),
1887 .driver_data = pch_ml7223_uart0},
1888 {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D),
1889 .driver_data = pch_ml7223_uart1},
Tomoya MORINAGA8249f742011-10-28 09:38:49 +09001890 {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8811),
1891 .driver_data = pch_ml7831_uart0},
1892 {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8812),
1893 .driver_data = pch_ml7831_uart1},
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001894 {0,},
1895};
1896
Bill Pemberton9671f092012-11-19 13:21:50 -05001897static int pch_uart_pci_probe(struct pci_dev *pdev,
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001898 const struct pci_device_id *id)
1899{
1900 int ret;
1901 struct eg20t_port *priv;
1902
1903 ret = pci_enable_device(pdev);
1904 if (ret < 0)
1905 goto probe_error;
1906
Tomoya MORINAGA4564e1e2011-01-28 18:00:01 +09001907 priv = pch_uart_init_port(pdev, id);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001908 if (!priv) {
1909 ret = -EBUSY;
1910 goto probe_disable_device;
1911 }
1912 pci_set_drvdata(pdev, priv);
1913
1914 return ret;
1915
1916probe_disable_device:
Alexander Steine4635952011-07-04 08:58:31 +02001917 pci_disable_msi(pdev);
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001918 pci_disable_device(pdev);
1919probe_error:
1920 return ret;
1921}
1922
Vaibhav Gupta23a98b6e2020-07-20 17:34:15 +05301923static SIMPLE_DEV_PM_OPS(pch_uart_pci_pm_ops,
1924 pch_uart_pci_suspend,
1925 pch_uart_pci_resume);
1926
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001927static struct pci_driver pch_uart_pci_driver = {
1928 .name = "pch_uart",
1929 .id_table = pch_uart_pci_id,
1930 .probe = pch_uart_pci_probe,
Bill Pemberton2d47b712012-11-19 13:21:34 -05001931 .remove = pch_uart_pci_remove,
Vaibhav Gupta23a98b6e2020-07-20 17:34:15 +05301932 .driver.pm = &pch_uart_pci_pm_ops,
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001933};
1934
1935static int __init pch_uart_module_init(void)
1936{
1937 int ret;
1938
1939 /* register as UART driver */
1940 ret = uart_register_driver(&pch_uart_driver);
1941 if (ret < 0)
1942 return ret;
1943
1944 /* register as PCI driver */
1945 ret = pci_register_driver(&pch_uart_pci_driver);
1946 if (ret < 0)
1947 uart_unregister_driver(&pch_uart_driver);
1948
1949 return ret;
1950}
1951module_init(pch_uart_module_init);
1952
1953static void __exit pch_uart_module_exit(void)
1954{
1955 pci_unregister_driver(&pch_uart_pci_driver);
1956 uart_unregister_driver(&pch_uart_driver);
1957}
1958module_exit(pch_uart_module_exit);
1959
1960MODULE_LICENSE("GPL v2");
1961MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver");
Ben Hutchings52592da2013-09-01 19:26:37 +01001962MODULE_DEVICE_TABLE(pci, pch_uart_pci_id);
1963
Tomoya MORINAGA3c6a4832010-11-17 09:55:54 +09001964module_param(default_baud, uint, S_IRUGO);
Darren Harta46f5532012-03-09 09:51:52 -08001965MODULE_PARM_DESC(default_baud,
1966 "Default BAUD for initial driver state and console (default 9600)");
Darren Hart2a44feb2012-03-09 09:51:50 -08001967module_param(user_uartclk, uint, S_IRUGO);
Darren Harta46f5532012-03-09 09:51:52 -08001968MODULE_PARM_DESC(user_uartclk,
1969 "Override UART default or board specific UART clock");